2015-03-04 4 views
5

У меня есть унаследованного кода, которые ставят объекты, как HTTP атрибуты сеанса, используя такой код:Как придать атрибут HTTP сеанса боба с помощью CDI

MyObject object = new MyObject(); 
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap(); 
sessionMap.put("attrname", object); 

Старые Facelets доступ код, используя

@ManagedProperty("#{attrname}") 
private MyObject object; 

Есть ли способ использовать CDI (@Inject), чтобы ввести этот атрибут сеанса в Bean?

В новом коде, который использует CDI, лучший способ создать и ввести объекты, которые необходимо создать контролируемым образом.

ответ

7

Получить его в сеансе с управляемым bean-компонентом с @Produces@Named на геттере.

@SessionScoped 
public class MyObjectProducer implements Serializable { 

    private MyObject myObject; 

    @Produces 
    @Named("attrname") 
    public MyObject getMyObject() { 
     return myObject; 
    } 

    public void setMyObject(MyObject myObject) { 
     this.myObject = myObject; 
    } 

} 

Когда вы устанавливаете его каким-либо образом через, например, myObjectProducer.setMyObject(myObject) в другом месте (или, возможно, событие CDI @Observes), вы можете вводить его в любом месте, используя @Inject @Named.

@Inject 
@Named("attrname") 
private MyObject myObject; 

И да, он по-прежнему доступен через #{attrname} в EL обычным способом. И нет, он не будет автоматически создан, если не установлен, он останется null, пока вы не установите его как свойство класса-производителя.


В качестве альтернативы, если вы действительно намерены сохранить унаследованную способ настройки экземпляра с помощью ExternalContext#getSessionMap() (например, потому, что третья сторона, и вы можете таким образом не изменить его), то вы можете в качестве альтернативы также позволяет производителю вернуть его непосредственно от сеанса карты:

@SessionScoped 
public class MyObjectProducer implements Serializable { 

    @Produces 
    @Named("attrname") 
    public MyObject getMyObject() { 
     return (MyObject) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("attrname"); 
    } 

} 

Это, однако, не гарантирует работу при введении в не JSF артефакта, такие как произвольное @WebServlet, как FacesContext#getCurrentInstance(), очевидно, вернется null.

+0

Спасибо @BalusC за быстрый и полный ответ. –

+2

Возможно, ответ может быть еще более полным, говоря, что для доступа к производителю из не управляемого кода используется этот код 'CDI.current(). Select (MyObjectProducer.class) .get()'. –

1

Это путь, как для артефактов, не связанных с jsf, так и jsf.

@Qualifier 
@Retention(RUNTIME) 
@Target({TYPE,METHOD,FIELD,PARAMETER}); 
public @interface SessionAttribute { 

    @NonBinding 
    String value() default ""; 
} 

@ApplicationScope 
public class SessionAttributeService { 

    //Dont worry, this is a proxy, and CDI will ensure that the right one called at the right time. 
    @Inject 
    private HttpServletRequest servletRequest; 

    @Produces 
    @SessionAttribute 
    @RequestScope 
    public String sessionAttribute(final InjectionPoint ip){ 
    final SessionAttribute sa = ip.getAnnotated().getAnnotation(SessionAttribute.class); 
    final HttpSession session = servletRequest.getSession(); 
    return session.getAttribute(sa.value()); 
    } 
} 

И Прецедент:

@RequestScope 
public class MyServiceBean { 

    @Inject 
    @SessionAttribute("theAttribute") 
    private String attribute; 

} 
+0

Это не способно вводить значения, отличные от String, такие как OP. Я бы очень определенно не назвал это «способ пойти» для «атрибутов сеанса» в целом. – BalusC

+1

Действительно @BalusC я просто привел пример, используя строки, он может просто изменить тип на все, что захочет ??? – maress

Смежные вопросы