복붙노트

[SPRING] 스프링 MVC 사용자 정의 범위 Bean

SPRING

스프링 MVC 사용자 정의 범위 Bean

내가 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 세션을 얻을 수 있습니까? ServletContext 범위에서 bean을 생성한다면 ServletContextAware 인터페이스를 구현할 것이라는 것을 이해합니다.

도와주세요 :)

해결법

  1. ==============================

    1.나는 그것이 미래에 누군가에게 유용 할 것이기를 희망합니다. 그래서 그것을 공유하고 싶습니다.

    나는 그것이 미래에 누군가에게 유용 할 것이기를 희망합니다. 그래서 그것을 공유하고 싶습니다.

    나는 그것에 대해 조사한 결과 유감스럽게도 Spring MVC를위한 HTTP Session을 얻는 것이 불가능하다는 것을 알게되었습니다.

    나의 목적은 PRG 패턴을 사용하여 스프링 MVC 컨트롤러를위한 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;
    
        /**
         * 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<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 );
                }
            }
        }
    
        /**
         * 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<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;
        }
    
    
    
        /** 
         * Starts a new scope. 
         * All items added in the session before the previous session are removed.
         * All items added in the previous scope are still retrievable and removable.
         */ 
        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" class="x.y.z.FlashScopeInterceptor" />
    <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
      <property name="interceptors">
        <list><ref bean="flashScopeInterceptor"/></list>
      </property>
    </bean> 
    
  2. ==============================

    2.org.springframework.web.context.request.SessionScope의 소스 코드를 살펴 보는 것이 좋습니다. 이 범위는 같은 문제를 어떻게 해결 했어야 만합니다.

    org.springframework.web.context.request.SessionScope의 소스 코드를 살펴 보는 것이 좋습니다. 이 범위는 같은 문제를 어떻게 해결 했어야 만합니다.

    그들이 사용하는 것처럼 보입니다. RequestContextHolder.currentRequestAttributes (). getSessionId ()

  3. ==============================

    3.Spring MVC (3.2에서 작동)의 scope 클래스 메소드에서 다음 코드를 사용하여 세션 속성에 액세스 할 수있다.

    Spring MVC (3.2에서 작동)의 scope 클래스 메소드에서 다음 코드를 사용하여 세션 속성에 액세스 할 수있다.

    RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
    attributes.getAttribute("some key", NativeWebRequest.SCOPE_SESSION);
    attributes.setAttribute("some key", YouObject, NativeWebRequest.SCOPE_SESSION);
    

    RequestAttributes 구현 (ServletRequestAttributes)은 내부적으로 현재 세션 객체에 대해 set / getAttribute () 메소드를 호출합니다.

  4. from https://stackoverflow.com/questions/5863472/spring-mvc-custom-scope-bean by cc-by-sa and MIT license