Весной MVC
Я хотел бы создать свой собственный настраиваемый компонент, который будет использовать HTTP-сеанс (вид флэш-области).
Согласно Spring Manual, мне нужно реализовать интерфейс org.springframework.beans.factory.config.Scope
public class CustomScope implements Scope { @Override public Object get(String arg0, ObjectFactory arg1) { // TODO Auto-generated method stub return null; } @Override public String getConversationId() { // TODO Auto-generated method stub return null; } @Override public void registerDestructionCallback(String arg0, Runnable arg1) { // TODO Auto-generated method stub } @Override public Object remove(String arg0) { // TODO Auto-generated method stub return null; } @Override public Object resolveContextualObject(String arg0) { // TODO Auto-generated method stub return null; } }
Мой вопрос: как я могу получить HTTP-сессию внутри этого компонента? Я понимаю, что если бы я создавал bean-компонент в области ServletContext, я бы использовал интерфейс ServletContextAware.
- Передача нескольких переменных в @RequestBody controllerу Spring MVC с использованием Ajax
- Что рекомендуется для нереста streamов из сервлета в Tomcat
- @ModelAttribute аннотация, когда ее использовать?
- как получить параметр в методе post spring mvc?
- log4j: WARN Для журнала в web.xml не найдено никаких добавлений.
Пожалуйста помоги 🙂
- Запрос, отправленный клиентом, был синтаксически неправильным. Шаблон Spring MVC + JDBC
- Как вручную установить аутентифицированного пользователя в Spring Security / SpringMVC
- Что вызывает «java.lang.IllegalStateException: ни BindingResult, ни обычный целевой объект для bean name« command », ansible как атрибут запроса»?
- Как отправлять данные POST JSON с помощью Curl из терминала / командной строки для тестирования Spring REST?
- Возврат JsonObject с помощью @ResponseBody в SpringMVC
- Бесконечная recursion с выпуском Jackson JSON и Hibernate JPA
- Каков правильный способ использования Spring MVC с Hibernate в DAO, архитектуры уровня обслуживания
- Почему DispatcherServlet создает другой контекст приложения?
Я надеюсь, что это будет полезно для кого-то в будущем, поэтому я хотел бы поделиться им.
Я сделал некоторое исправление и обнаружил, что, к сожалению, невозможно получить HTTP-сеанс для Spring MVC.
Моя цель – реализация Flash Scope для моего controllerа Spring MVC с использованием шаблона PRG.
Сделав больше исследований в Spring Forum, я нашел способ сделать это с помощью 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; /** * Unbinds current flashScope from session. Rolls request's flashScope to * the next scope. Binds request's flashScope, if not empty, to the session. * */ @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 ); } } } } /** * merge modelAndView.model['flashScope'] to current flashScope */ @Override public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (modelAndView != null) { Map modelFlashScopeMap = null; for (Iterator> iterator = ((Map) modelAndView.getModel()).entrySet() .iterator(); iterator.hasNext();) { Entry 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(); } 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 ); } } } /** * binds session flashScope to current session, if not empty. Otherwise cleans up empty * flashScope */ @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() ); } } /** Shadows composite map. */ private final LinkedList
Применение:
@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}
Кроме того, вам необходимо настроить class FlashScopeInterceptor как перехватчик.
Я рекомендую посмотреть исходный код org.springframework.web.context.request.SessionScope . Эта область действия должна решить одну и ту же проблему.
Похоже, они используют: RequestContextHolder.currentRequestAttributes().getSessionId()
Вы можете получить доступ к атрибутам сеанса, используя следующий код в методах classа scope в Spring MVC (работает в 3.2):
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); attributes.getAttribute("some key", NativeWebRequest.SCOPE_SESSION); attributes.setAttribute("some key", YouObject, NativeWebRequest.SCOPE_SESSION);
Реализация RequestAttributes (ServletRequestAttributes) внутренне вызовет методы set / getAttribute () для текущего объекта сеанса.