- 手艺 tags:
- Grails
- java
- web published: true comments: true
Grails的在Servlet API的基础上增加了一个非常实用的FlashScope,FlashScope的生命周期为两次请求(也就是在一次重定向)。它的典型应用是POST方式提交后显示服务器端发给用户的提示信息,在平时的应用中会经常使用。
Grails的FlashScope接口定义在org.codehaus.groovy.grails.web.servlet包中,这个接口继承了Map接口,并定义了一个方法next()。
Grails的默认实现在org.codehaus.groovy.grails.web.servlet包中,GrailsFlashScope。这个实现内部定义了两个Map(生命周期为两个请求),current和next,这两个Map不断滚动,保持在一个请求中可以且仅可以访问到当前和前一次请求的上下文。
[codesyntax lang="java"]
public void next() {
current.clear();
current = (HashMap)next.clone();
next.clear();
reassociateObjectsWithErrors(current);
}
[/codesyntax]
put的时候,Grails只把新制放到next表中,因为next将在下一次请求时继续保存
[codesyntax lang="java"]
public Object put(Object key, Object value) {
// create the session if it doesn't exist
registerWithSessionIfNecessary();
if(current.containsKey(key)) {
current.remove(key);
}
storeErrorsIfPossible(next,value);
return next.put(key,value);
}
[/codesyntax]
get的时候,Grails在两个Map中查找
[codesyntax lang="java"]
public Object get(Object key) {
if(next.containsKey(key))
return next.get(key);
return current.get(key);
}
[/codesyntax]
此外,FlashScope本身还是被放在session中
[codesyntax lang="java"]
private void registerWithSessionIfNecessary() {
GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes();
HttpSession session = webRequest.getCurrentRequest().getSession(true);
if(session.getAttribute(GrailsApplicationAttributes.FLASH_SCOPE) == null)
session.setAttribute(GrailsApplicationAttributes.FLASH_SCOPE, this);
}
[/codesyntax]
然后,滚动FlashScope的行为在GrailsWebRequestFilter中被调用,GrailsWebRequestFilter继承自spring-web的OncePerRequestFilter
[codesyntax lang="java"]
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
...
// Set the flash scope instance to its next state. We do
// this here so that the flash is available from Grails
// filters in a valid state.
FlashScope fs = webRequest.getAttributes().getFlashScope(request);
fs.next();
...
}
[/codesyntax]