struts2应用程序中的会话

时间:2011-04-01 05:46:08

标签: java session java-ee struts2

我创建了一个Web应用程序,我需要维护会话 如果有用户会话,那么只有这样才允许用户看到jsp。

之前我曾使用过jsp servlet,但我是struts2的新手。

此处我在我的操作类中设置用户名

修订代码

private HttpSession session;

public void setSession(HttpSession session) {
    // TODO Auto-generated method stub0
    this.session = session;
}

public HttpSession getSession() {
    return session;
}

public String getLoginStatus(){     
    session = request.getSession();
    session.setAttribute("userName", loginBean.getUsername());
    return SUCCESS;
}

现在,当我在操作后重定向到下一页时,它会显示一次会话值。之后,在每个页面上,我在会话中找到空值。

<%
    String userName = (String)session.getAttribute("userName");             
    System.out.println(userName);                        

    if(userName == null || userName.equals("") ){
        response.sendRedirect("login.jsp");
    }

%>

我在某处读到动作类会话的范围仅限于一页 - 我该如何解决这个问题?

任何例子都对我很有帮助。

6 个答案:

答案 0 :(得分:35)

您目前的代码存在一些问题。

  • 您应该使用Interceptor强制用户登录,而不是尝试在JSP中强制执行。 JSP应仅用于表示,而不用于流控制。
  • 您应该避免使用JSP中的scriptlet(代码块)。很久以前就被弃用了,并且在MVC应用程序中被广泛认为是一种非常糟糕的做法。
  • 您可以直接访问JSP中的会话值。除非您需要访问操作本身内部的会话,否则无需在操作中实现SessionAware接口。
  • 您应该将用户重定向到登录操作,而不是直接转到JSP页面,否则您将绕过Struts2框架并失去使用框架的好处。

登录示例

下面是一些使用Struts2框架创建基本登录系统的示例代码。

需要登录

这部分是可选的,但一般而言,并非Web应用程序中的所有页面都需要用户登录。因此,让我们创建一个名为LoginRequired的界面。如果用户尚未登录,则实现此标记界面的任何操作都将重定向到登录页面。

注意:如果您愿意,可以使用注释,但是对于此示例,我将使用该界面。

public interface LoginRequired {}

拦截器

拦截器将处理强制用户登录任何实现LoginRequired接口的请求操作。

public class LoginInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(final ActionInvocation invocation) throws Exception {
        Map<String, Object> session = ActionContext.getContext().getSession();

        // sb: feel free to change this to some other type of an object which
        // represents that the user is logged in. for this example, I am using
        // an integer which would probably represent a primary key that I would
        // look the user up by with Hibernate or some other mechanism.
        Integer userId = (Integer) session.get("userId");

        // sb: if the user is already signed-in, then let the request through.
        if (userId != null) {
            return invocation.invoke();
        }

        Object action = invocation.getAction();

        // sb: if the action doesn't require sign-in, then let it through.
        if (!(action instanceof LoginRequired)) {
            return invocation.invoke();
        }

        // sb: if this request does require login and the current action is
        // not the login action, then redirect the user
        if (!(action instanceof LoginAction)) {
            return "loginRedirect";
        }

        // sb: they either requested the login page or are submitting their
        // login now, let it through
        return invocation.invoke();
    }
}

您还需要一个显示和处理登录页面的LoginAction和一个使会话无效或清除的LogoutAction

配置

您需要将拦截器添加到堆栈中,并为“loginRedirect”创建全局结果映射。

<interceptors>
    <interceptor name="login" class="your.package.LoginInterceptor"/>

    <!-- sb: you need to configure all of your interceptors here. i'm only
         listing the one we created for this example. -->
    <interceptor-stack name="yourStack">
        ...
        <interceptor-ref name="login"/>
        ...
    </interceptor-stack>
</interceptors>

<global-results>
    <!-- sb: make this the path to your login action.
         this could also be a redirectAction type. -->
    <result name="loginRedirect" type="redirect">/login</url>
</global-results>

答案 1 :(得分:6)

要维护会话,请在您的操作类中使用 SessionAware 接口并实现int public void setSession(Map m)它会将该属性作为map中的键值对 可以从任何只需购买钥匙的地方进行访问。

例如动作类

import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

public class LogingEx extends ActionSupport implements SessionAware{
    private static final long serialVersionUID = 1L;

    private String stuname,stuage,country;
    private int stumarks;
    Map m;

    public String getStuname() {
        return stuname;
    }
    public void setStuname(String stuname) {
        this.stuname = stuname;
    }

    public String getStuage() {
        return stuage;
    }
    public void setStuage(String stuage) {
        this.stuage = stuage;
    }

    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }

    public int getStumarks() {
        return stumarks;
    }
    public void setStumarks(int stumarks) {
        this.stumarks = stumarks;
    }

    public void setSession(Map m)
    {
        this.m=m;
    }

    public String execute()
    {
        m.put("a",stuname);
        m.put("b", stuage);
        m.put("c",stumarks);
        m.put("d",country);

        return SUCCESS;
    }

}

消息来源:http://www.java4s.com/struts-tutorials/example-on-struts-2-sessionaware-interface/

答案 2 :(得分:2)

我发现没有理由使用这种Map来授权用户。如果你的要求只是针对会话验证用户,那么我建议使用Filter而不是某些类中的某些地图,这种地图的问题是在会话失效后删除会话对象,当然你可以使用HttpSessionListener使其正常运行但我认为最好通过Filter进行验证而不是Map

除此之外,您还可以查看许多安全框架(如Apache Shiro),以使您的任务更简单,更健壮。

答案 3 :(得分:2)

您的Action类是否已实现SessionAware界面?

编辑:

试试这个(这是一个struts2风格的解决方案):

public class anAction implements SessionAware{
    private Map<String, Object> session;
    public Map<String, Object> getSession() {
         return session;
    }
    public void setSession(Map<String, Object> session) {
         this.session = session;
    }
    public String getLoginStatus(){
         session.put("userName", "test");  //Hard code here for testing.
         return SUCCESS;
    }
}

然后使用您的jsp代码在页面上获取userName。我已经在我的机器上测试了这种方法,但它确实有效。

EDIT2: 顺便说一句,使用Struts2 Framework提供的“Interceptor”可以轻松完成这种登录检查。

答案 4 :(得分:0)

不需要SessionAware实现。

public class LoginAction extends Actionsupport
{
  private Map<String, Object> session;
  //Getter and Setter method
   public String execute() throws Exception {
      session=ActionContext.getContext().getSession();
      session.put("userName", "test");
     return super.execute();
   }
} 

答案 5 :(得分:0)

以下期刊文章在http://www.journaldev.com/2210/struts-2-interceptor-tutorial-with-custom-authentication-interceptor-example

之上的Steven回复的同一行中有更多细节