编辑:好吧,所以我试着设置一些console.writes来检查发生了什么。。。我的注销脚本似乎是在导航时调用的。但除了在我的注销按钮上,我不会在任何地方调用它。
这是我的模板代码:
<div class="navbar">
<div class="navbar-inner">
<ul class="nav">
<li class="active"><a href="#{root}index.xhtml">Home</a></li>
<li><a href="#{root}races/list.xhtml">Races</a></li>
<li><a href="#{root}horses/list.xhtml">Horses</a></li>
<h:panelGroup rendered="#{memberController.logged == true}">
<li><a href="#{root}profile/history.xhtml">History</a></li>
<li><a href="#" onclick="#{memberController.logout()}">Logout</a></li>
</h:panelGroup>
<h:panelGroup rendered="#{memberController.logged == false}">
<li><a href="#{root}users/login.xhtml">Login</a></li>
<li><a href="#{root}users/register.xhtml">Create Account</a></li>
</h:panelGroup>
</ul>
</div>
</div>
原始消息:
我正在为我的学校项目(Java EE(创建一个网站。。。这是我们第一年这么做。现在,由于这是夜校,而且只学习了一个学期,你可能会发现我的做事方式并不是最好的:(
因此,为了开始,我试图创建一个登录功能,但我们可以使用简单会话范围的成员对象来代替那些混乱的安全代码行。
这里有一些我的课程:
会员类别:
@Entity
@Table(name = "members")
public class Member implements Serializable {
//+ Getters, setters, HashCode and equals
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private long id;
private double money;
@NotNull(message = "Username cannot be null")
@Size(min = 4, message = "Username should be of minimum 4 characters")
private String userName;
@NotNull(message = "Password cannot be null")
@Size(min = 4, message = "Password should be of minimum 4 characters")
private String password;
@PostPersist
private void initDefault() {
this.money = 500;
}
}
MemberBean类:
@Stateless
public class MemberBean {
@PersistenceContext(unitName="HorseRacingPU")
private EntityManager em;
public Member getMember(long id){
return em.find(Member.class, id);
}
public Member getMember(String username, String password){
TypedQuery<Member> q = em.createQuery("SELECT u FROM Member u WHERE u.userName=?1 AND u.password=?2", Member.class);
q.setParameter(1, username);
q.setParameter(2, password);
return q.getSingleResult();
}
public List<Member> getAllMembers(){
TypedQuery<Member> q = em.createQuery("SELECT u FROM Member u", Member.class);
return q.getResultList();
}
public Member addOrUpdateMember(Member u){
Member original = em.find(Member.class, u.getId());
if(original == null){
em.persist(u);
return u;
}else{
return em.merge(u);
}
}
public Member deleteMember(long id){
Member original = em.find(Member.class, id);
if(original != null){
em.remove(original);
}
return original;
}
}
MemberController类:
@SessionScoped
public class MemberController implements Serializable {
@EJB
private MemberBean bean;
private String username;
private String password;
private Member member;
private boolean logged = false;
// + their getters and setters
public List<Member> getAllMembers() {
return bean.getAllMembers();
}
public String login() {
member = bean.getMember(username, password);
if (member != null) {
logged = true;
return "/races/list.xhtml?faces-redirect=true";
}
return "/users/login.xhtml?faces-redirect=true";
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "/index.xhtml?faces-redirect=true";
}
public void checkLogin(ComponentSystemEvent e) {
if (!logged) {
FacesContext context = FacesContext.getCurrentInstance();
ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
handler.performNavigation("/users/login.xhtml?faces-redirect=true");
}
}
public Member getMember() {
return member;
}
public void submit() {
bean.addOrUpdateMember(member);
}
}
我得到的主要错误如下:
信息:处理试图重置响应的错误时发生异常。
可以在此处找到更具体的详细错误:http://pastebin.com/h5nTNnes
所以,当我登录时,一切都很好。当我导航到另一个url(在转发到/races/list后(时,我会被注销。当我使用checkLogin((:时,错误本身就会显示出来
<f:event type="preRenderView" listener="#{memberController.checkLogin}" />
我不确定这是否相关,但当我在没有任何演示数据(或凭据错误(的情况下登录时,我会得到一个评估异常,并且无法检索到任何实体。以下是更多详细信息:http://pastebin.com/Tv9mQ1K9
这可能是什么?我挠头三天了,似乎哪里都找不到问题。
这个,
<li><a href="#" onclick="#{memberController.logout()}">Logout</a></li>
是不对的。
onclick
属性应该引用一个JavaScript处理程序。例如alert('peek-a-boo');
。JSF/EL将其视为一个普通的字符串,并期望logout()
方法以String
的形式返回一些JavaScript代码,然后将其内联在HTML结果中。假设该方法实际返回alert('peek-a-boo');
,那么最终结果(如您在浏览器中右键单击所见,ViewSource(将是:
<li><a href="#" onclick="alert('peek-a-boo');">Logout</a></li>
然而,在您的特定情况下,您实际上正在执行注销并返回一个字符串值/index.xhtml?faces-redirect=true
。因此生成的HTML最终成为
<li><a href="#" onclick="/index.xhtml?faces-redirect=true">Logout</a></li>
这是无效的JS代码。但这并不是主要问题:用户在没有点击链接的情况下就被注销了!
您需要一个完整的JSF命令组件。例如<h:commandLink>
。
<li><h:form><h:commandLink value="Logout" action="#{memberController.logout()}"/></h:form></li>
该方法只在实际单击链接时调用,这正是您所需要的。