好的,这是我的会话bean。我总是可以从任何Servlet或Filter中检索currentUser。这不是问题问题是fileList和currentFile。我用简单的int和Strings进行了测试,并且它的效果相同。如果我从视图范围bean中设置一个值,我可以从另一个类中获取数据。
@ManagedBean(name = "userSessionBean")
@SessionScoped
public class UserSessionBean implements Serializable, HttpSessionBindingListener {
final Logger logger = LoggerFactory.getLogger(UserSessionBean.class);
@Inject
private User currentUser;
@EJB
UserService userService;
private List<File> fileList;
private File currentFile;
public UserSessionBean() {
fileList = new ArrayList<File>();
currentFile = new File("");
}
@PostConstruct
public void onLoad() {
Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
String email = principal.getName();
if (email != null) {
currentUser = userService.findUserbyEmail(email);
} else {
logger.error("Couldn't find user information from login!");
}
}
这是一个例子。
我的视图范围豆。这是它的装饰方式。
@ManagedBean
@ViewScoped
public class ViewLines implements Serializable {
@Inject
private UserSessionBean userSessionBean;
现在代码。
userSessionBean.setCurrentFile(file);
System.out.println("UserSessionBean : " + userSessionBean.getCurrentFile().getName());
我可以完美地看到当前的文件名。这实际上是从jsf动作方法打印的。显然当前的文件正在设置中。
现在,如果我这样做。
@WebFilter(value = "/Download")
public class FileFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpSession session = ((HttpServletRequest) request).getSession(false);
UserSessionBean userSessionBean = (UserSessionBean) session.getAttribute("userSessionBean");
System.out.println(userSessionBean.getCurrentUser().getUserId()); //works
System.out.println("File filter" + userSessionBean.getCurrentFile().getName()); //doesn't work
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
currentUser显示正常,但我看不到该文件。它只是空白。 Strings,int等也会发生同样的事情。
感谢您提供的任何帮助。
INFO:UserSessionBean:第3B行 - 8531268875812004316.csv(从视图范围内的bean打印的值)
信息:文件过滤器tester.csv(运行过滤器时打印的值。)
这很有用。
FacesContext context = FacesContext.getCurrentInstance();
userSessionBean = (UserSessionBean) context.getApplication().evaluateExpressionGet(context, "#{userSessionBean}", UserSessionBean.class);
我把它放在ViewScoped的构造函数中,一切都很好。现在为什么不按照我的想法进行注射?起初我想也许是因为我使用的是JSF托管bean而不是新的CDI bean。但是我将bean更改为新样式(带有命名),这也是同样的效果。
注入是否只允许您访问bean但不更改其属性?
答案 0 :(得分:5)
你正在混合JSF和CDI。您的UserSessionBean
是一个JSF @ManagedBean
,但您正在使用CDI @Inject
将其注入另一个bean。 CDI不重用JSF托管的,而是创建一个全新的。使用其中一个,而不是两个。注入JSF管理的bean的正确注释是@ManagedProperty
。
替换
@Inject
private UserSessionBean userSessionBean;
通过
@ManagedProperty(value="#{userSessionBean}")
private UserSessionBean userSessionBean;
并确保您的代码中没有import javax.enterprise.context
(这是CDI注释包)。
或者,将所有JSF bean管理批注迁移到CDI bean管理批注。
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
@Named
@SessionScoped
public class UserSessionBean implements Serializable {}
import javax.inject.Named;
import javax.faces.view.ViewScoped;
@Named
@ViewScoped
public class ViewLines implements Serializable {}
另外一个好处是,您可以在常规servlet或过滤器中@Inject
,而无需手动将其作为请求/会话/应用程序属性获取。
此外,自JSF 2.3以来,不推荐使用JSF bean管理注释。另请参阅Backing beans (@ManagedBean) or CDI Beans (@Named)?
答案 1 :(得分:0)
我最好的GUESS为什么会发生这种情况,是因为变量文件是在视图范围内设置的,然后通过引用传递给会话范围的bean。也许这种情况正在发生,因为当视图范围bean被销毁时,它仍然具有对该变量的引用,但是不会在会话范围内查看是否存在对其进行的任何其他引用,应该保留它。因此,当它被销毁时,在这种情况下它会从视图和会话范围中删除。
您可以尝试使用“new”实例化的对象调用setCurrentFile吗?这可能证明或反驳了我的这个假设。
否则,我最好的建议是破解调试器,并确切了解更改getCurrentFile的位置。