⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 session.java

📁 Wicket一个开发Java Web应用程序框架。它使得开发web应用程序变得容易而轻松。 Wicket利用一个POJO data beans组件使得它可以与任何持久层技术相结合。
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.wicket;import java.io.Serializable;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Locale;import java.util.Map;import java.util.Set;import java.util.Map.Entry;import org.apache.wicket.application.IClassResolver;import org.apache.wicket.authorization.IAuthorizationStrategy;import org.apache.wicket.feedback.FeedbackMessage;import org.apache.wicket.feedback.FeedbackMessages;import org.apache.wicket.protocol.http.IgnoreAjaxRequestException;import org.apache.wicket.request.ClientInfo;import org.apache.wicket.session.ISessionStore;import org.apache.wicket.util.lang.Objects;import org.apache.wicket.util.string.Strings;import org.apache.wicket.util.time.Duration;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Holds information about a user session, including some fixed number of most recent pages (and all * their nested component information). * <ul> * <li><b>Access via RequestCycle </b>- The Session for a {@link RequestCycle} can be retrieved by * calling {@link RequestCycle#getSession()}. *  * <li><b>Access via Component </b>- If a RequestCycle object is not available, the Session can be * retrieved for a Component by calling {@link Component#getSession()}. As currently implemented, * each Component does not itself have a reference to the session that contains it. However, the * Page component at the root of the containment hierarchy does have a reference to the Session that * holds the Page. So {@link Component#getSession()} traverses the component hierarchy to the root * Page and then calls {@link Page#getSession()}. *  * <li><b>Access via Thread Local </b>- In the odd case where neither a RequestCycle nor a * Component is available, the currently active Session for the calling thread can be retrieved by * calling the static method Session.get(). This last form should only be used if the first two * forms cannot be used since thread local access can involve a potentially more expensive hash map * lookup. *  * <li><b>Locale </b>- A session has a Locale property to support localization. The Locale for a * session can be set by calling {@link Session#setLocale(Locale)}. The Locale for a Session * determines how localized resources are found and loaded. *  * <li><b>Style </b>- Besides having an appearance based on locale, resources can also have * different looks in the same locale (a.k.a. "skins"). The style for a session determines the look * which is used within the appropriate locale. The session style ("skin") can be set with the * setStyle() method. *  * <li><b>Resource Loading </b>- Based on the Session locale and style, searching for resources * occurs in the following order (where sourcePath is set via the ApplicationSettings object for the * current Application, and style and locale are Session properties): * <ul> * 1. [sourcePath]/name[style][locale].[extension] <br> * 2. [sourcePath]/name[locale].[extension] <br> * 3. [sourcePath]/name[style].[extension] <br> * 4. [sourcePath]/name.[extension] <br> * 5. [classPath]/name[style][locale].[extension] <br> * 6. [classPath]/name[locale].[extension] <br> * 7. [classPath]/name[style].[extension] <br> * 8. [classPath]/name.[extension] <br> * </ul> *  * <li><b>Session Properties </b>- Arbitrary objects can be attached to a Session by installing a * session factory on your Application class which creates custom Session subclasses that have * typesafe properties specific to the application (see {@link Application} for details). To * discourage non-typesafe access to Session properties, no setProperty() or getProperty() method is * provided. In a clustered environment, you should take care to call the dirty() method when you * change a property on your own. This way the session will be reset again in the http session so * that the http session knows the session is changed. *  * <li><b>Class Resolver </b>- Sessions have a class resolver ( {@link IClassResolver}) * implementation that is used to locate classes for components such as pages. *  * <li><b>Page Factory </b>- A pluggable implementation of {@link IPageFactory} is used to * instantiate pages for the session. *  * <li><b>Removal </b>- Pages can be removed from the Session forcibly by calling remove(Page) or * removeAll(), although such an action should rarely be necessary. *  * <li><b>Flash Messages</b>- Flash messages are messages that are stored in session and are * removed after they are displayed to the user. Session acts as a store for these messages because * they can last across requests. *  * @author Jonathan Locke * @author Eelco Hillenius * @author Igor Vaynberg (ivaynberg) */public abstract class Session implements IClusterable{	/**	 * Visitor interface for visiting page maps	 * 	 * @author Jonathan Locke	 */	public static interface IPageMapVisitor	{		/**		 * @param pageMap		 *            The page map		 */		public void pageMap(final IPageMap pageMap);	}	/**	 * meta data for recording map map access.	 */	public static final class PageMapAccessMetaData implements IClusterable	{		private static final long serialVersionUID = 1L;		Set pageMapNames = new HashSet(2);		/**		 * @param pagemap		 *            the pagemap to add as used.		 * @return the boolean if it was added (didn't already contain the pagemap)		 */		public boolean add(IPageMap pagemap)		{			return pageMapNames.add(pagemap.getName());		}	}	/** meta data key for missing body tags logging. */	public static final MetaDataKey PAGEMAP_ACCESS_MDK = new MetaDataKey(		PageMapAccessMetaData.class)	{		private static final long serialVersionUID = 1L;	};	/** Name of session attribute under which this session is stored */	public static final String SESSION_ATTRIBUTE_NAME = "session";	/** Thread-local current session. */	private static final ThreadLocal current = new ThreadLocal();	/** A store for dirty objects for one request */	private static final ThreadLocal dirtyObjects = new ThreadLocal();	/** Logging object */	private static final Logger log = LoggerFactory.getLogger(Session.class);	/** Attribute prefix for page maps stored in the session */	private static final String pageMapAttributePrefix = "m:";	private static final long serialVersionUID = 1L;	/** A store for touched pages for one request */	private static final ThreadLocal touchedPages = new ThreadLocal();	/** Prefix for attributes holding page map entries */	static final String pageMapEntryAttributePrefix = "p:";	/**	 * Checks if the <code>Session</code> threadlocal is set in this thread	 * 	 * @return true if {@link Session#get()} can return the instance of session, false otherwise	 */	public static boolean exists()	{		return current.get() != null;	}	/**	 * Locate the session for the client of this request in the {@link ISessionStore} or create a	 * new one and attach it when none could be located and sets it as the current instance for this	 * thread. Typically, clients never touch this method, but rather use {@link Session#get()},	 * which does the locating implicitly when not yet set as a thread local.	 * 	 * @return The session for the client of this request or a new, unbound	 */	public static final Session findOrCreate()	{		RequestCycle requestCycle = RequestCycle.get();		if (requestCycle == null)		{			throw new IllegalStateException(				"you can only locate or create sessions in the context of a request cycle");		}		Response response = requestCycle.getResponse();		Request request = requestCycle.getRequest();		return findOrCreate(request, response);	}	/**	 * @param response	 * @param request	 * @return The Session that is found in the current request or created if not.	 */	public static Session findOrCreate(Request request, Response response)	{		Application application = Application.get();		ISessionStore sessionStore = application.getSessionStore();		Session session = sessionStore.lookup(request);		if (session == null)		{			// Create session using session factory			session = application.newSession(request, response);		}		// set thread local		set(session);		return session;	}	/**	 * Get the session for the calling thread.	 * 	 * @return Session for calling thread	 */	public static Session get()	{		Session session = (Session)current.get();		if (session == null)		{			session = findOrCreate();		}		return session;	}	/**	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.	 * <p>	 * Sets session for calling thread. Also triggers {@link #attach()} being called.	 * 	 * @param session	 *            The session	 */	public static void set(final Session session)	{		if (session == null)		{			throw new IllegalArgumentException("Argument session can not be null");		}		current.set(session);		// execute any attach logic now		session.attach();	}	/**	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.	 * <p>	 * Clears the session for calling thread.	 * 	 */	public static void unset()	{		current.set(null);	}	/** A number to generate names for auto create pagemaps */	private int autoCreatePageMapCounter = 0;	/**	 * Cached instance of agent info which is typically designated by calling	 * {@link RequestCycle#newClientInfo()}.	 */	private ClientInfo clientInfo;	/** True if session state has been changed */	private transient boolean dirty = false;	/** feedback messages */	private final FeedbackMessages feedbackMessages = new FeedbackMessages();	/** cached id because you can't access the id after session unbound */	private String id = null;	/** The locale to use when loading resources for this session. */	private Locale locale;	/** Application level meta data. */	private MetaDataEntry[] metaData;	/**	 * We need to know both thread that keeps the pagemap lock and the RequestCycle	 */	private static class PageMapsUsedInRequestEntry	{		Thread thread;		RequestCycle requestCycle;	};	private transient Map pageMapsUsedInRequest;	/** True, if session has been invalidated */	private transient boolean sessionInvalidated = false;	/**	 * Temporary instance of the session store. Should be set on each request as it is not supposed	 * to go in the session.	 */	private transient ISessionStore sessionStore;	/** Any special "skin" style to use when loading resources. */	private String style;	/**	 * Holds attributes for sessions that are still temporary/ not bound to a session store. Only	 * used when {@link #isTemporary()} is true.	 * <p>	 * Note: this doesn't have to be synchronized, as the only time when this map is used is when a	 * session is temporary, in which case it won't be shared between requests (it's a per request	 * instance).	 * </p>	 */	private transient Map temporarySessionAttributes;	/** A linked list for last used pagemap queue */	private final LinkedList/* <IPageMap> */usedPageMaps = new LinkedList();	/**	 * Constructor. Note that {@link RequestCycle} is not available until this constructor returns.	 * 	 * @param request	 *            The current request	 */	public Session(Request request)	{		locale = request.getLocale();		if (locale == null)		{			throw new IllegalArgumentException("Parameter 'locale' must not be null");		}	}	/**	 * Constructor. Note that {@link RequestCycle} is not available until this constructor returns.	 * 	 * @deprecated Use #Session(Request)	 * 	 * @param application	 *            The application that this is a session of	 * @param request	 *            The current request	 */	protected Session(Application application, Request request)	{		this(request);	}	/**	 * Force binding this session to the application's {@link ISessionStore session store} if not	 * already done so.	 * <p>	 * A Wicket application can operate in a session-less mode as long as stateless pages are used.	 * Session objects will be then created for each request, but they will only live for that	 * request. You can recognize temporary sessions by calling {@link #isTemporary()} which	 * basically checks whether the session's id is null. Hence, temporary sessions have no session	 * id.	 * </p>	 * <p>	 * By calling this method, the session will be bound (made not-temporary) if it was not bound	 * yet. It is useful for cases where you want to be absolutely sure this session object will be	 * available in next requests. If the session was already bound ({@link ISessionStore#lookup(Request) returns a session}),	 * this call will be a noop.	 * </p>	 */	public final void bind()	{		// If there is no request cycle then this is not a normal request but for example a last		// modified call.		if (RequestCycle.get() == null)			return;		ISessionStore store = getSessionStore();		Request request = RequestCycle.get().getRequest();		if (store.lookup(request) == null)		{			// explicitly create a session			id = store.getSessionId(request, true);			// bind it			store.bind(request, this);			if (temporarySessionAttributes != null)			{				for (Iterator i = temporarySessionAttributes.entrySet().iterator(); i.hasNext();)				{					Entry entry = (Entry)i.next();					store.setAttribute(request, String.valueOf(entry.getKey()), entry.getValue());				}				temporarySessionAttributes = null;			}		}	}	/**	 * Cleans up all rendered feedback messages and any unrendered, dangling feedback messages there	 * may be left after that.	 */	public abstract void cleanupFeedbackMessages();	/**	 * Removes all pages from the session. Although this method should rarely be needed, it is	 * available (possibly for security reasons).	 */	public final void clear()	{		visitPageMaps(new IPageMapVisitor()		{			public void pageMap(IPageMap pageMap)			{				pageMap.clear();			}		});	}	/**	 * Automatically creates a page map, giving it a session unique name.	 * 	 * @return Created PageMap	 */	public final IPageMap createAutoPageMap()	{		return newPageMap(createAutoPageMapName());	}	protected int currentCreateAutoPageMapCounter()	{		return autoCreatePageMapCounter;	}	protected void incrementCreateAutoPageMapCounter()	{		++autoCreatePageMapCounter;	}	/**	 * With this call you can create a pagemap name but not create the pagemap itself already. It	 * will give the first pagemap name where it couldn't find a current pagemap for.	 * 	 * It will return the same name if you call it 2 times in a row.	 * 	 * @return The created pagemap name	 */	public synchronized final String createAutoPageMapName()	{		String name = getAutoPageMapNamePrefix() + currentCreateAutoPageMapCounter() +			getAutoPageMapNameSuffix();		IPageMap pm = pageMapForName(name, false);		while (pm != null)		{			incrementCreateAutoPageMapCounter();			name = getAutoPageMapNamePrefix() + currentCreateAutoPageMapCounter() +				getAutoPageMapNameSuffix();			pm = pageMapForName(name, false);		}		return name;	}	/**	 * @return The prefixed string default "wicket-".	 */	protected String getAutoPageMapNamePrefix()	{		return "wicket-";	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -