Each request receives its own stream, so the request, response, parameters, session, etc. available regardless of whether the controller is single or created new for each request. It would be different if these variables were fields in the class, but this is not so.
Under the hood, this is implemented by the AST transformation, which is mixed in org.codehaus.groovy.grails.plugins.web.api.ControllersApi in controller classes, which adds methods like getParams() (which you can use as the params property). They call RequestContextHolder.currentRequestAttributes() to get the stream information.
source share