我对此进行了一些研究,发现不幸的是,无法获得Spring MVC的HTTP会话。
我的目的是使用PRG模式为Spring MVC Controller实现Flash Scope。
在Spring论坛中进行更多研究后,我找到了使用HandlerInterceptor进行编码的方法。
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.util.*;import java.util.Map.Entry;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;public class FlashScopeInterceptor implements HandlerInterceptor { public static final String DEFAULT_ATTRIBUTE_NAME = "flashScope"; public static final String DEFAULT_SESSION_ATTRIBUTE_NAME = FlashScopeInterceptor.class.getName(); public static final int DEFAULT_RETENTION_COUNT = 2; private String sessionAttributeName = DEFAULT_SESSION_ATTRIBUTE_NAME; private String attributeName = DEFAULT_ATTRIBUTE_NAME; private int retentionCount = DEFAULT_RETENTION_COUNT; @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { if (request.getSession( false ) != null) { request.getSession().removeAttribute( this.sessionAttributeName ); } Object requestAttribute = request.getAttribute( this.attributeName ); if (requestAttribute instanceof MultiScopeModelMap) { MultiScopeModelMap attributes = (MultiScopeModelMap) requestAttribute; if (!attributes.isEmpty()) { attributes.next(); if (!attributes.isEmpty()) { request.getSession( true ).setAttribute( this.sessionAttributeName, attributes ); } } } } @Override public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (modelAndView != null) { Map<String, Object> modelFlashScopeMap = null; for (Iterator<Entry<String, Object>> iterator = ((Map<String, Object>) modelAndView.getModel()).entrySet() .iterator(); iterator.hasNext();) { Entry<String, Object> entry = iterator.next(); if (this.attributeName.equals( entry.getKey() ) && entry.getValue() instanceof Map) { if (modelFlashScopeMap == null) { modelFlashScopeMap = (Map) entry.getValue(); } else { modelFlashScopeMap.putAll( (Map) entry.getValue() ); } iterator.remove(); } else if (entry.getKey().startsWith( this.attributeName + "." )) { String key = entry.getKey().substring( this.attributeName.length() + 1 ); if (modelFlashScopeMap == null) { modelFlashScopeMap = new HashMap<String, Object>(); } modelFlashScopeMap.put( key, entry.getValue() ); iterator.remove(); } } if (modelFlashScopeMap != null) { MultiScopeModelMap flashScopeMap; if (request.getAttribute( this.attributeName ) instanceof MultiScopeModelMap) { flashScopeMap = (MultiScopeModelMap) request.getAttribute( this.attributeName ); } else { flashScopeMap = new MultiScopeModelMap( this.retentionCount ); } flashScopeMap.putAll( modelFlashScopeMap ); request.setAttribute( this.attributeName, flashScopeMap ); } } } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession( false ); if (session != null) { Object sessionAttribute = session.getAttribute( this.sessionAttributeName ); if (sessionAttribute instanceof MultiScopeModelMap) { MultiScopeModelMap flashScope = (MultiScopeModelMap) sessionAttribute; if (flashScope.isEmpty()) { session.removeAttribute( this.sessionAttributeName ); } else { request.setAttribute( this.attributeName, flashScope ); } } } return true; }}现在MultiScopeModelMap.java
import java.io.Serializable;import java.util.Collection;import java.util.HashMap;import java.util.linkedList;import java.util.Map;import java.util.Set;import org.apache.commons.collections.map.CompositeMap;import org.apache.commons.collections.map.CompositeMap.MapMutator;public class MultiScopeModelMap extends CompositeMap implements Serializable, MapMutator{ public MultiScopeModelMap(int num) { super(); setMutator( this ); for(int i = 0; i < num; ++i) { addComposited( new HashMap() ); } } private final linkedList<Map> maps = new linkedList<Map>(); @Override public synchronized void addComposited( Map map ) throws IllegalArgumentException { super.addComposited( map ); this.maps.addLast( map ); } @Override public synchronized Map removeComposited( Map map ) { Map removed = super.removeComposited( map ); this.maps.remove( map ); return removed; } public void next() { removeComposited( this.maps.getFirst() ); addComposited( new HashMap() ); } public Object put( CompositeMap map, Map[] composited, Object key, Object value ) { if(composited.length < 1) { throw new UnsupportedOperationException("No composites to add elements to"); } Object result = map.get( key ); if(result != null) { map.remove( key ); } composited[composited.length-1].put( key, value ); return result; } public void putAll( CompositeMap map, Map[] composited, Map mapToAdd ) { for(Entry entry: (Set<Entry>)mapToAdd.entrySet()) { put(map, composited, entry.getKey(), entry.getValue()); } } public void resolveCollision( CompositeMap composite, Map existing, Map added, Collection intersect ) { existing.keySet().removeAll( intersect );} @Override public String toString() { return new HashMap(this).toString(); }}用法:
@RequestMapping(value="/login.do", method=RequestMethod.POST) public ModelAndView login(@Valid User user){ ModelAndView mv = new ModelAndView("redirect:result.html"); if (authService.authenticate(user.getUserName(), user.getPassword())) mv.addObject("flashScope.message", "Success"); //else mv.addObject("flashScope.message", "Login Failed"); return mv; }@RequestMapping(value ="/result.html", method=RequestMethod.GET) public ModelAndView result(){ ModelAndView mv = new ModelAndView("login/loginAction"); return mv; }在JSP中,用法非常简单:
${flashScope.message}另外,你需要将FlashScopeInterceptor类配置为拦截器。
<bean id="flashScopeInterceptor" /><bean id="handlerMapping" > <property name="interceptors"> <list><ref bean="flashScopeInterceptor"/></list> </property></bean>



