Your requirement is very similar, but opposite, to my case of server caching dynamic reports.
I had on-demand statistical reports that took a long time to generate, so that if someone had already requested for that page, the cached page would be served rather than re-generating it.
Your case is, once a page is served, do not serve it again.
Either way, we need a persistent flag or signature on each page. That flag or signature would have to sit on a persistent datastore.
Managing innumerable possible pages
If you have to manage an innumerable number of pages like I had to, since the number of on-demand http-parameter driven dynamic pages are of infinite possible number of pages, you cannot have simple single persistent flag. I had a routine to compress the http post/get request parameters into a unique signature. That signature is persisted. So that when a request comes in, the http parameters are run thro this signature generator and the resultant signature is compared against the persistent datastore to search if the signature is already existent.
In my case, if the signature is existent, I serve the cached page. In your case, if the signature is existent, you show an error page.
First-come-first-served affected by time events
However, in both our cases "page served for the first time" can be affected by time events. In my case, when new data is uploaded - that signature is stale. So, I have to ensure my statistical information schema is time-based - with the time of dataload or time of event. So that the signature has two components, the http parametric signature and the event/load time of the requested entity. If the signature matches, but that the latest time of the requested entity stored in the database is greater than the one persisted in the signature, that means the request is considered "a new page".
You have to decide for yourself how to design http parameters that would help you generate the shortest possible signature and decide what parameters would make a page unique.
As for the persistent store, since I was already using oracle to store the statistical info, I had as well used the same oracle database to persist the signatures. Otherwise, I think hsqldb might be a good solution.
Signature strategy
The signature table would consist of three fields: event datetime, ownersemaphore, unique key paramsig.
Where, to keep the table from growing beyond current signatures, a stale signature is overwritten during signature comparison. I also had a job deleting stale signatures.
Multi-user access is managed very simply by placing a paramsig with a null datetime. In my case, I could assure myself that request datetime is unique so that I actually used the request datetime as ownersemaphore. The first lucky person (but in my case the unlucky first user who needed to wait for an uncached report) to race to the table and create that unique paramsig would cause subsequent attempts to be thrown out by the database system. The null datetime is inform that a paramsig is being reserved and will be filled in later. In your case, you might be able to skip that step and just use paramsig, ownersemaphore.
However, if you are in a multiserver env, you need to devise a composite key for ownersemaphore, like server id + request time.
I'm not sure if hsqldb is able to manage concurrency. I have only done this strategy on oracle and sqlserver.