📜  Struts 2和Spring集成的登录示例(1)

📅  最后修改于: 2023-12-03 14:47:44.342000             🧑  作者: Mango

Struts 2 和 Spring 集成的登录示例

在 Web 应用程序中,登录功能通常是必不可少的。本文将介绍一个基于 Struts 2 和 Spring 框架的登录示例,演示如何在 Web 应用程序中实现登录和访问控制。

技术栈
  • Struts 2
  • Spring
  • Hibernate
  • MySQL
数据库设计

本示例需要一个用户表来存储用户名和密码信息。以下是用户表的设计:

CREATE TABLE users (
    id INT(11) NOT NULL AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(50) NOT NULL,
    PRIMARY KEY (id)
);
配置 Struts 2

首先,需要在 web.xml 文件中配置 Struts 2 的过滤器和监听器:

<!-- Struts 2 Filter -->
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Struts 2 Listener -->
<listener>
    <listener-class>org.apache.struts2.dispatcher.ng.listener.StrutsListener</listener-class>
</listener>

其次,在 struts.xml 文件中配置登录和访问控制的相关信息:

<struts>
  <package name="login" namespace="/" extends="struts-default">
    <action name="login" class="com.example.LoginAction">
      <result name="success">/welcome.jsp</result>
      <result name="error">/login.jsp</result>
    </action>

    <action name="logout" class="com.example.LogoutAction">
      <result name="success">/login.jsp</result>
    </action>
  </package>

  <constant name="struts.custom.i18n.resources" value="global" />
  <constant name="struts.devMode" value="false" />

  <interceptors>
    <interceptor name="authInterceptor" class="com.example.AuthInterceptor" />
    <interceptor-stack name="authStack">
      <interceptor-ref name="authInterceptor" />
      <interceptor-ref name="defaultStack" />
    </interceptor-stack>
  </interceptors>

  <default-interceptor-ref name="authStack" />

  <global-results>
    <result name="logout">/login.jsp</result>
  </global-results>
</struts>
  • 登录操作的 Action 名称为 login,其类为 com.example.LoginAction,用于验证用户名和密码是否正确;
  • 成功登录后,将跳转到 /welcome.jsp 页面,登录失败则跳转回 /login.jsp
  • 注销操作的 Action 名称为 logout,其类为 com.example.LogoutAction,用于清除登录状态;
  • 配置一个名为 authStack 的拦截器栈,包含一个名为 authInterceptor 的拦截器和 defaultStack 栈;
  • authStack 拦截器栈设置为默认拦截器栈;
  • 配置全局的 logout 结果。
配置 Spring

为了将 Struts 2 和 Spring 集成起来,需要在 struts.xml 文件中引入 Spring 的配置文件:

<struts>
  <!-- ... 略 ... -->

  <constant name="struts.objectFactory" value="spring" />
  <constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true" />

  <bean type="com.example.UserService" name="userService" class="com.example.UserServiceImpl">
    <property name="userDao" ref="userDao" />
  </bean>

  <bean type="com.example.UserDao" name="userDao" class="com.example.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
    <property name="username" value="root" />
    <property name="password" value="passw0rd" />
  </bean>

  <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.example.entity" />
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
      </props>
    </property>
  </bean>
</struts>

其中,

  • 将 Struts 2 的对象工厂设置为 Spring;
  • 声明 UserService 和 UserDao 的 Spring Bean,并注入依赖(UserServiceImpl 依赖 UserDao,UserDaoImpl 依赖 Hibernate 的 SessionFactory);
  • 配置了一个名为 dataSource 的 Spring Bean,作为 Hibernate 的数据源;
  • 声明了 sessionFactory Spring Bean,注入 dataSourcehibernateProperties,其中指定了 Hibernate 方言为 MySQL 5 和数据表自动更新。
编写代码

业务逻辑是这样的:在登录页面中输入用户名和密码,点击登录按钮,将用户名和密码发送给后台进行验证。在后台,通过 UserService 的方法调用查询数据库,根据查询结果判断登录是否成功。登录成功后,将用户信息保存在 Session 中,用于访问控制。注销操作将清除 Session 中的用户信息。

先看一下 UserService 接口和实现类:

public interface UserService {
    User getUserByUsername(String username);
}

@Service
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {
    private UserDao userDao;

    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    public User getUserByUsername(String username) {
        return userDao.getUserByUsername(username);
    }
}

其中,

  • UserService 定义了一个获取用户对象的方法;
  • UserServiceImpl 实现了 UserService,依赖 UserDao 进行数据访问,将 UserDao 注入进来,并在构造函数中进行了初始化。

接下来看一下 LoginAction:

public class LoginAction extends ActionSupport {
    private String username;
    private String password;

    @Autowired
    private UserService userService;

    public String execute() {
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            addActionError(getText("error.username.or.password.required"));
            return ERROR;
        }

        User user = userService.getUserByUsername(username);

        if (user == null || !password.equals(user.getPassword())) {
            addActionError(getText("error.username.or.password.invalid"));
            return ERROR;
        }

        HttpSession session = ServletActionContext.getRequest().getSession();
        session.setAttribute("currentUser", user);

        return SUCCESS;
    }

    // getters and setters
}

其中,

  • LoginAction 是一个 Struts 2 的 Action 类,用于处理登录操作;
  • @Autowired 注解用于将 UserService 注入进来;
  • execute() 方法中,首先判断用户名和密码是否为空,如果为空则返回一个错误信息;
  • 然后调用 UserService 查询数据库,根据查询结果判断用户名和密码是否正确,如果不正确则返回一个错误信息,返回跳转到登录页面;
  • 如果验证通过,将用户信息保存在 Session 中,返回跳转到欢迎页面。

最后,看一下访问控制的拦截器:

public class AuthInterceptor extends AbstractInterceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        HttpSession session = ServletActionContext.getRequest().getSession();

        if (session.getAttribute("currentUser") != null) {
            return invocation.invoke();
        } else {
            return "logout";
        }
    }
}

其中,

  • AuthInterceptor 继承 Struts 2 的 AbstractInterceptor 类,用于实现访问控制的逻辑;
  • intercept() 方法中,获取 Session 中保存的用户信息,如果存在则放行,否则返回一个名为 logout 的结果,跳转回登录页面。
总结

本文演示了在 Web 应用程序中如何实现登录和访问控制,同时介绍了 Struts 2 和 Spring 集成的方式。通过这个示例,你可以了解到 Struts 2 和 Spring 的基本使用方法,并学会了如何在 Web 应用程序中实现登录和访问控制。