서블릿 관련 클래스에서 이름으로 JSF 관리 Bean 가져 오기


101

@ManagedBeans이름 으로 참조하고 싶은 사용자 지정 서블릿 (AJAX / JSON 용)을 작성하려고합니다 . 다음을 매핑하고 싶습니다.

http://host/app/myBean/myProperty

에:

@ManagedBean(name="myBean")
public class MyBean {
    public String getMyProperty();
}

일반 서블릿에서 이름으로 빈을로드 할 수 있습니까? 사용할 수있는 JSF 서블릿이나 도우미가 있습니까?

나는이 모든 것이 너무 명백한 봄에 망가진 것 같다.


JSF / EL 외부에서 이러한 새 주석을 사용할 수 있는지 확실하지 않지만 JSR 299 사양을 살펴 보겠습니다
McDowell

비슷한 문제가있는 다른 사람들도 bpcatalog.dev.java.net/ajax/jsf-ajax 를 확인할 수 있습니다 (AJAX 및 요청 매핑 / 처리와 관련, 이름으로 빈을 얻지 않음)
Konrad Garus

답변:


263

@WebServlet, @WebFilter및과 같은 서블릿 기반 아티팩트에서 다음과 같은 방법으로 @WebListener"일반 바닐라"JSF @ManagedBean @RequestScoped를 얻을 수 있습니다.

Bean bean = (Bean) request.getAttribute("beanName");

그리고 @ManagedBean @SessionScoped:

Bean bean = (Bean) request.getSession().getAttribute("beanName");

그리고 @ManagedBean @ApplicationScoped:

Bean bean = (Bean) getServletContext().getAttribute("beanName");

이것은 빈이 이미 JSF에 의해 미리 자동 생성되어야한다는 것을 전제합니다. 그렇지 않으면 null. 그런 다음 수동으로 빈을 생성하고 setAttribute("beanName", bean).


@NamedJSF 2.3 deprecated 이후 대신 CDI를 사용할 수 있다면 @ManagedBean특히 더 이상 수동으로 빈을 생성 할 필요가 없기 때문에 훨씬 더 쉽습니다.

@Inject
private Bean bean;

@Named @ViewScoped빈은 JSF보기 상태로만 식별 할 수 있고이 FacesServlet호출 된 경우에만 사용할 수 있으므로 사용중인 경우에는 작동하지 않습니다 . 따라서 그 전에 실행되는 필터에서 @Injected에 액세스 @ViewScoped하면 항상 ContextNotActiveException.


내부에있을 때만 @ManagedBean다음을 사용할 수 있습니다 @ManagedProperty.

@ManagedProperty("#{bean}")
private Bean bean;

이것은 내부에서 작동하지 않습니다 @Named또는 @WebServlet또는 기타 유물. 실제로 내부 @ManagedBean에서만 작동 합니다.


당신이 안에하지 않은 경우 @ManagedBean지만,이 FacesContext(즉, 쉽게 사용할 수 FacesContext#getCurrentInstance()반환하지 않습니다 null), 당신은 또한 사용할 수 있습니다 Application#evaluateExpressionGet():

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);

다음과 같이 편리 할 수 ​​있습니다.

@SuppressWarnings("unchecked")
public static <T> T findBean(String beanName) {
    FacesContext context = FacesContext.getCurrentInstance();
    return (T) context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);
}

다음과 같이 사용할 수 있습니다.

Bean bean = findBean("bean");

또한보십시오:


9
당신은 콩을 주입하는 것에 대한 두 번째 제안이 너무 놀랍도록 단순해서 완전히 간과했습니다. 항상 그렇듯이 귀하의 응답은 완벽합니다. 여기에서 작업 해 주셔서 감사합니다.
jnt30 2011 년

2
그 동안 (JSF 2.2에서 말하면), 더 이상 캐스팅이 필요하지 않도록 예상되는 클래스를 지정할 수있는 세 번째 매개 변수를 사용하여 evaExpressionGet 메서드가 확장 된 것 같습니다. PostBean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", PostBean.class);
Marc Juchli 2014 년

1
@Marc : 처음부터 들어 왔습니다. 내가 생각하기에 복사 붙여 넣기 실수로 남은 것뿐입니다. 답변이 수정되었습니다. 알려 주셔서 감사합니다.
BalusC 2014 년

FacesContextstatic유틸리티 메소드 findBean()가 일반 Java 클래스 내에 정의되어 있어도 사용할 수 있습니다 . JSF에서 관리하지 않는 일반 Java 클래스에서 어떻게 사용할 수 있습니까?
Tiny

1
@Tiny : 동일한 스레드 내에서 JSF 아티팩트에 의해 차례로 호출됩니다.
BalusC 2015

11

다음 방법을 사용합니다.

public static <T> T getBean(final String beanName, final Class<T> clazz) {
    ELContext elContext = FacesContext.getCurrentInstance().getELContext();
    return (T) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, beanName);
}

이를 통해 반환 된 개체를 형식화 된 방식으로 가져올 수 있습니다.


3
이것은 이미 현재 받아 들여지는 답변과 더 편리한 방법으로 이미 다루어졌습니다 ( Class이 구조에서는 인수가 불필요합니다).
BalusC

3

이 링크와 같은 접근 방식을 시도해 보셨습니까? 나는 확실하지 않다createValueBinding()여전히 사용 가능한지 않지만 이와 같은 코드는 일반 오래된 서블릿에서 액세스 할 수 있어야합니다. 이것은 이미 존재하는 bean이 필요합니다.

http://www.coderanch.com/t/211706/JSF/java/access-managed-bean-JSF-from

 FacesContext context = FacesContext.getCurrentInstance();  
 Application app = context.getApplication();
 // May be deprecated
 ValueBinding binding = app.createValueBinding("#{" + expr + "}"); 
 Object value = binding.getValue(context);

이것은 아마도 일반 서블릿에서 작동하지 않을 것입니다. FacesContext는 JSF 라이프 사이클 (일반적으로 FacesServlet)에 의해 설정된 요청 별 스레드 로컬 아티팩트입니다.
McDowell

7
ValueBinding은 4 년 전에 JSF 1.2부터 사용되지 않습니다.
BalusC 2010

@BalusC : 내가 얼마나 최신인지 보여줍니다. 참고로, 검색 엔진을 사용하여 기술을 연구하는 것은 기존의 모든 정보에 비생산적인 것으로 밝혀졌습니다. @McDowell : 실제로 말이됩니다. 무슨 일이 일어나는지 시험해 볼게요.
James P.

3

이름을 전달하여 관리 Bean을 가져올 수 있습니다.

public static Object getBean(String beanName){
    Object bean = null;
    FacesContext fc = FacesContext.getCurrentInstance();
    if(fc!=null){
         ELContext elContext = fc.getELContext();
         bean = elContext.getELResolver().getValue(elContext, null, beanName);
    }

    return bean;
}

서블릿에서 시도했지만 작동하지 않습니다.
Fernando Pie

0

나는 같은 요구 사항이 있었다.

나는 그것을 얻기 위해 아래 방법을 사용했습니다.

세션 범위 빈이 있습니다.

@ManagedBean(name="mb")
@SessionScopedpublic 
class ManagedBean {
     --------
}

내 서블릿 doPost () 메서드에서 아래 코드를 사용했습니다.

ManagedBean mb = (ManagedBean) request.getSession().getAttribute("mb");

그것은 내 문제를 해결했습니다.


어떤 종류의 서블릿을 사용하십니까? mate
Fernando Pie

1
HttpServlet입니다.
Anil

-1

나는 이것을 사용한다 :

public static <T> T getBean(Class<T> clazz) {
    try {
        String beanName = getBeanName(clazz);
        FacesContext facesContext = FacesContext.getCurrentInstance();
        return facesContext.getApplication().evaluateExpressionGet(facesContext, "#{" + beanName + "}", clazz);
    //return facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, nomeBean);
    } catch (Exception ex) {
        return null;
    }
}

public static <T> String getBeanName(Class<T> clazz) {
    ManagedBean managedBean = clazz.getAnnotation(ManagedBean.class);
    String beanName = managedBean.name();

    if (StringHelper.isNullOrEmpty(beanName)) {
        beanName = clazz.getSimpleName();
        beanName = Character.toLowerCase(beanName.charAt(0)) + beanName.substring(1);
    }

    return beanName;
}

그리고 전화 :

MyManageBean bean = getBean(MyManageBean.class);

이렇게하면 코드를 리팩터링하고 문제없이 사용량을 추적 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.