实例解析Struts 2.1与Sping、Hibernate集成

来源:互联网 发布:mysql 最近一年 编辑:程序博客网 时间:2024/06/01 08:18

实例解析Struts 2.1与Sping、Hibernate集成

 

Spring本身提供了一套极其优秀的MVC框架,但这套框架的设计过于复杂,采用了大量的映射策略,Struts 2是以Webwork 2作为基础发展出来。而在Webwork 2.2之前的Webwork版本,其自身有一套控制反转的实现,Webwork 2.2Spring 框架的如火如荼发展的背景下,决定放弃控制反转功能的开发,转由Spring实现。因此,Struts 2推荐通过Spring实现控制反转。

13.4.1  配置应用项目

首先用Myeclipse开发向导创建一个Web应用项目,在本例中创建的项目名为sshapp,然后把下载的struts-2.1.6-all.zip解压包中lib目录中的struts2-spring-plugin-2.1.6.jarcommons-logging.jarfreemarker.jarognl.jarstruts2-core.jarxwork.jar commons-io-1.3.2.jar commons-fileupload-1.2.1.jar (lib目录中Struts 2框架的类库有版本后缀。例如commons-logging.jar,可能是commons-logging-1.0.4.jarstruts2-core.jar可能是struts2-core-2.1.6.jar)加入到项目的WEB-INF/lib目录中,这里需要确保这些包的版本一致,在struts-2.1.6-all.zip解压包中的lib目录中存放的是spring-core-2.0.8.jar包,并没有spring-core-2.5.3.jar,如果用spring-core-2.0.8.jar包,启动Tomcat6时会出现“java.lang.ClassNotFoundException: org.springframework.core.SmartClassLoader”错误提示,可以从struts-2.1.6-all.zip包的apps目录中的struts2-showcase-2.1.6.war包中的WEB-INF/lib目录中找到spring-core-2.5.3.jar包。接下来需要修改WEB-INF/web.xml文件内容,添加内容如下:

<listener>

        <listener-class>

            org.springframework.web.context.ContextLoaderListener

        </listener-class >

</listener>

上面的配置主要是加入SpringContextLoaderListener监听器,方便SpringWeb容器交互。紧接着修改Struts.properties文件,以便Struts 2运行时使用Spring来创建对象(如Action等),添加内容如下:

struts.objectFactory =spring

 

13.4.2  创建实体表

MySQL中先创建一个数据库,名称为hibernatedb,然后创建用户表user,创建表的SQL内容如清单13-32所示。

清单13-32

CREATE TABLE  hibernatedb.user (

  id int(10) NOT NULL auto_increment

  name varchar(50) NOT NULL

  password varchar(16) NOT NULL

  PRIMARY KEY  (id)

);

13.4.3  创建Hibernate框架

在本例中,以前面创建的sshapp项目为基础,来创建Hibernate应用。首先在MyEclipse中选中sshapp项目,然后单击右键,在弹出的菜单中选择MyEclipse项下的项Add Hibernate Capabilites项,弹出如图13-5所示界面,在本例中,选择的Hibernate版本是3.2,其他选择MyEclipse默认的值,然后单击Next按钮弹出如13-6所示按钮,在这里将创建hibernate.cfg.xml配置文件。 MyEclipse中,设置数据库的连接,并将所需的MySQLjdbc类库拷贝到lib目录中。然后使用MyEclipse的数据Database Explorer向导工具创建User.hbm.xmlUser.java映射文件。User.java代码清单13-33所示。

清单13-33

public class User extends AbstractUser implements java.io.Serializable {

    // Fields

    private Integer id;

    private String name;

    private String password;

    // Constructors

    public User() {

    }

    // Property accessors

    public Integer getId() {

        return this.id;

    }

    public void setId(Integer id) {

        this.id = id;

    }

    public String getName() {

        return this.name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getPassword() {

        return this.password;

    }

    public void setPassword(String password) {

        this.password = password;

    }

}

User.hbm.xml内容如清单13-34所示。

清单13-34

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="com.hibernate.bean.User" table="user" catalog="hibernatedb">

        <id name="id" type="java.lang.Integer">

            <column name="id" />

            <generator class="identity" />

        </id>

        <property name="name" type="java.lang.String">

            <column name="name" length="50" not-null="true" />

        </property>

        <property name="password" type="java.lang.String">

            <column name="password" length="16" not-null="true" />

        </property>

    </class>

</hibernate-mapping>

 生成的hibernate.cfg.xml配置文件内容如清单13-35所示。

清单13-35

<?xml version="1.0" encoding="gb2312"?>

<!DOCTYPE hibernate-configuration PUBLIC

    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- 显示实际操作数据库时的SQL -->

        <property name="show_sql">true</property>

        <property name="format_sql">false</property>

        <property name="cache.use_query_cache">false</property>

        <!-- SQL方言,这边设定的是MySQL -->

        <!-- JDBC驱动程序 -->

        <property name="dialect">

            org.hibernate.dialect.MySQLDialect</property>

        <property name="connection.driver_class">

            com.mysql.jdbc.Driver</property>

        <property name="connection.url">

            jdbc:mysql://localhost/hibernatedb

        </property>

        <property name="connection.username">root</property>

        <property name="connection.password">12345</property>

        <!-- 对象与数据库表格映像文件 -->

        <mapping resource="ch11/hibernate/User.hbm.xml" />

    </session-factory>

</hibernate-configuration>

      

13-5  导入Hibernate                             13-6  创建Hibernate配置

 

13.4.4  创建DAO

UserDAO接口程序如清单13-36所示。

清单13-36

package com.hibernate.dao;

import com.hibernate.bean.User;

public interface UserDAO {

    public abstract boolean isValidUser(String username,String password);

    public void save(User user);

    public void delete(User user);

    public User findById(int id);

}

在创建Hibernate3.2 + Spring2.5+Struts2.1应用程序时,需要相应的类库,应用MyEclipse开发时,可通过开发向导导入所需要的包,具体方法在新建的项目上,单击右键,在弹出的菜单中选择Properties项,弹出如图13-7所示对话框。在对话框中选择Java Build Path项。在右边选择第三个TabLibraries,列出了当前项目己添加的类库,要添加MyEclipse中的类库,单击Add Library按钮,弹出如图13-8 所示对话框。在弹出的对话框中选择MyEclipse Libraties项,单击Next按钮,进入MyEclipse Libratis库的选择界面,如图13-9所示。本例选择的类库有Spring 2.5 AOP LibratiesSpring 2.5 Core LibratiesSpring2.0 Persistence Core LibratiesSpring 2.5 Web Libraties

 

13-7  类库配置页面

 

     

13-8  MyEclipse类库                          13-9  选择类库

 

作者提示:在整合Sping2.5+Struts2.1 +Hibernate3.2中,在启动服务器时会出现java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit导常,这是由于Spring 2.5 Hibernate 3.2共用的一些 jar 文件发生了版本冲突。解决的办法是在MyEclipse的主菜单WindowPreferencesMyeclipseProject项中,选择CapabilitiesSpring项,从lib中删除asm-2.2.3.jar包即可。如果项目的WEB-INF/lib目录下有asm-2.2.3.jar包,则需要删除该包。

UserDAO接口实现类UserDAOImp代码如清单13-37所示。

清单13-37

package com.hibernate.dao;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.hibernate.bean.User;

import java.io.Serializable;

import java.util.List;

import org.hibernate.Query;

import org.hibernate.SessionFactory;

public class UserDAOImp extends HibernateDaoSupport implements UserDAO {

private SessionFactory sessionFactory;

private static String hql = "select u from User u where u.name=? and password=? ";

    public boolean isValidUser(String name, String password) {// 验证登录

        String para[] = new String[2];

        para[0] = name;

        para[1] = password;

        Query query = this.getHibernateTemplate().getSessionFactory()

                .openSession().createQuery(hql);

        query.setParameter(0, para[0]);

        query.setParameter(1, para[1]);

        List userList = query.list();

        try {

            if (userList.isEmpty()) {

                return false;

            }

        } catch (Exception ex) {

            ex.printStackTrace();

        }

        return true;

    }

    public void save(User user) {// 保存

        this.getHibernateTemplate().save(user);

    }

    public void delete(User user) {// 删除用户

        this.getHibernateTemplate().delete(user);

    }

    public User findById(Serializable id) {// 根据ID查找

        return (User) this.getHibernateTemplate().get(User.class, id);

    }

    public User findById(int id) {

        return (User) this.getHibernateTemplate().get(User.class, id);

    }

}

13.4.4  创建Action

接下来修改LoginAction.java代码,使用UserDAO的方法来进行用户验证,代码如清单13-38所示。

清单13-38

package com.struts2.action;

import com.hibernate.dao.UserDAO;

import com.opensymphony.xwork2.ActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {

    private static final long serialVersionUID = 1L;

    private UserDAO userDAO; // 依赖于Spring注入

    private String name;

    private String password;

    public UserDAO getUserDAO() {

        return userDAO;

    }

    public void setUserDAO(UserDAO userDAO) {

        this.userDAO = userDAO;

    }

    public String getName() {

        return this.name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getPassword() {

        return this.password;

    }

    public void setPassword(String password) {

        this.password = password;

    }

    // 处理用户请求的execute方法

    public String execute() throws Exception {

        System.out.println("执行操作");

       

        if (userDAO.isValidUser(this.getName(), this.getPassword())) {

            ActionContext.getContext().getSession().put("user", getName());

            return this.SUCCESS;

        } else

            return this.ERROR;

       

    }

    // 完成输入校验需要重写的validate方法

    public void validate() {// 如果用户名为空,或者用户名为空字符串

        System.out.println("校验输入");

        if (getName() == null || getName().trim().equals("")) {// 添加表单校验错误

            addFieldError("name", getText("user.required"));

        }// 当密码为空,或者密码为空字符串时,添加表单校验错误

        if (getPassword() == null || getPassword().trim().equals("")) {

            addFieldError("pass", getText("pass.required"));

        }

    }

}

上面定义的LoginAction类使用属性(Getter/Setter)注入方法取得userDAO对象。

13.4.5  创建Spring应用

接下来创建Spring的配置文件applicationContext.xml,把该文件存放在项目的WEB-INF目录下,配置内容如清单13-39所示。

清单13-39

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.1.xsd">

    <!-- Hibernate设置 -->

    <!-- 会话工厂设置,读取Hibernate数据库配置信息 -->

    <bean id="sessionFactory"

        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

        <property name="configLocation">

            <value>classpath:hibernate.cfg.xml</value>

            <!--直接引入Hibernate配置方法 -->

        </property>

    </bean>

    <!-- Spring设置 -->

    <!-- 会话模板 -->

    <bean id="hibernateTemplate"

        class="org.springframework.orm.hibernate3.HibernateTemplate">

        <property name="sessionFactory">

            <ref bean="sessionFactory" />

        </property>

    </bean>

    <!-- 事务管理器 -->

    <bean id="transactionManager"

        class="org.springframework.orm.hibernate3.HibernateTransactionManager">

        <property name="sessionFactory">

            <ref local="sessionFactory" />

        </property>

    </bean>

    <!--  配置UserDAOImpl持久化类的DAO bean-->

    <bean id="userDAO" class="com.hibernate.dao.UserDAOImp">

        <!--采用依赖注入来传入SessionFactory的引用-->

        <property name="sessionFactory">

            <ref local="sessionFactory" />

        </property>

    </bean>

    <!-- 配置事务拦截器-->

    <bean id="transactionInterceptor"

        class="org.springframework.transaction.interceptor.TransactionInterceptor">

        <!-- 事务拦截器bean 需要依赖注入一个事务管理器-->

        <property name="transactionManager">

            <ref local="transactionManager" />

        </property>

        <property name="transactionAttributes">

            <!-- 下面定义事务传播属性-->

            <props>

                <prop key="save">PROPAGATION_REQUIRED</prop>

                <prop key="dele*">PROPAGATION_REQUIRED</prop>

 

            </props>

        </property>

    </bean>

    <!--定义BeanNameAutoProxyCreator ,该bean 是个bean 后处理器,无须被引用,因此

        没有id 属性,这个bean 后处理器,根据事务拦截器为目标bean 自动创建事务代理-->

    <bean class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

        <!--指定对满足哪些bean name bean 自动生成业务代理-->

        <property name="beanNames">

            <!-- 下面是所有需要自动创建事务代理的bean-->

            <list>

                <value>userDAO</value>

            </list><!--  此处可增加其他需要自动创建事务代理的bean-->

        </property>

        <!--下面定义BeanNameAutoProxyCreator所需的事务拦截器-->

        <property name="interceptorNames">

            <list>

                <value>transactionInterceptor</value>

            </list>

        </property>

        </bean>

        <!-- 设置代理Struts动作 -->

        <bean name="loginAction" class="com.struts2.action.LoginAction"

            scope="prototype">

            <property name ="userDAO">

            <ref local ="userDAO" />

        </property>

        </bean>

</beans>

在上面的配置中,Struts 2会为每一个请求创建一个Action对象,所以在定义LoginAction时应用scope="prototype"属性。这样Spring会为每个调用者返回一个新的LoginAction对象。 因为userDAO被配置为默认的scope(也即是singleton,单根模式),所以在实现时应保证其线程安全。

上面定义的Actionstruts.xml中的配置内容如清单13-41所示。

清单13-41

<!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"

        "http://struts.apache.org/dtds/struts-2.1.dtd">

<struts>

    <include file="struts-default.xml" />

    <package name="Spring" extends="struts-default">

        <action name="loginaction" class="loginAction">

            <result name="success">/index.jsp</result>

            <result name="error">/sshlogin.jsp</result>

             <result name="input">/sshlogin.jsp</result>

        </action>

    </package>   

</struts>  

这里的Action       配置与前面不同的就是class属性,它对应于Spring所定义的beanid,而不是它的类全名。

13.4.6  测试部署应用

最后,定义一个显示用户列表的JSP文件sshlogin.jsp,实现代码如清单13-42所示。

清单13-42

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>

<html>

    <head>

    </head>

    <body>

        <!-- 提交请求参数的表单 -->

        <form action="loginaction.action" method="post" >

            <table align="center">

                <caption>

                    <h4>用户登录信息</h4>

                </caption>

                <tr><!-- 用户名的表单域 -->

                    <td>用户名:<input type="text" name="name" /></td></tr>

                <tr><td> &nbsp;

                <input type="password" name="password" style=" width : 149px;"/>

                </td></tr>

                <tr align="center">

                    <td colspan="2">

                        <input type="submit" value=" " />

                        <input type="reset" value=" " />

                    </td></tr>

            </table>

        </form>

    </body>

</html>

发布应用程序后,在浏览器地址栏中输入http://localhost:8081/sshapp/sshlogin.jsp,程序运行页面如图13-10所示。为了测试登录功能,可以先在前面创建的User表中录入一些用户信息,然后在如图13-10所示登录页面中测试。

13-10 登录页面

上面的应用程序介绍了一个简单的登录程序,演示如何整合Spring2.5Hibernate3.2Struts2.1三种技术。在本例中,应用Spring2.5作为整个系统的控制容器,Struts2.1Hibernate3.2Spring2.5的控制容器中工作。

原创粉丝点击