Struts2+Hibernate3.2+Spring 2.0整合应用

来源:互联网 发布:天猫魔盒ip地址端口号 编辑:程序博客网 时间:2024/06/04 08:27

首先我们要讲struts部分:

1.       struts.xml

开始要引入dtd,增加对struts标签的支持:

<!DOCTYPE struts PUBLIC

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

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

这样的话:就可以出现许多成对的标签了。

<struts></struts>

主要通过<package></package>来包含一个action。这个action相当于一个具有增删改查的功能 一体的action控制器.

举例: <action name="saveUser" class="saveUserAction">

                     <result name="success" type="redirect">listUser.action</result>

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

              </action>

这个action起到insert的作用,有两个结果:一是插入成功,然后重定向到一个action。二是数据输入失败,回到原来的页面

 

<action name="listUser" class="listUserAction">

                     <result>/list.jsp</result>

              </action>

这个action起到查询的作业,直接将结果输出到list.jsp显示.对应的actionlistUserAction.

<action name="updatePUser" class="updatePUserAction">

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

              </action>

这个action只是将页面传过来的user.id拿到update.jsp的一个hiden隐藏域中.

<action name="updateUser" class="updateUserAction">

                     <result name="success" type="redirect">listUser.action</result>

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

</action>

这个action实现的功能是将进行更新的操作,如果操作成功则重定向到listUser.action.如果修改有误,则重新回到该页面不做处理

 

       <action name="generateExcel" class="generateExcelAction">

                     <result name="success" type="stream">

                            <param name="contentType">application/vnd.ms-excel</param>

                            <param name="contentDisposition">filename="AllUsers.xls"</param>

                            <param name="inputName">downloadFile</param>

                     </result>

              </action>

这个action是一个无状态的。所谓无状态,是没有属性的。不会记录该action做完之后会留下什么东东。所以可以使用singletonspringcontext.xml文件中

这个action的功能是实现产生一个excel文件,提拱给前端下载的。<result type="stream" ></result>,这个type中选择stream类型的。就是以二进制的形式传递文件.

第一个参数:contentTypeapplication/vnd.ms-excel其实是产生文件的类型

第二个参数: contentDisposition指定下载时候的文件名: AllUsers.xls

第三个参数:inputName其实是提拱一个*downloadFile()的方法供action使用的.

 

注意:第一层是struts, 第二层是用package,第三层用action.第四层才用result..

 <!-- package提供了将多个Action组织为一个模块的方式
         package
的名字必须是唯一的 package可以扩展 当一个package扩展自
        
另一个package时该package会在本身配置的基础上加入扩展的package
        
的配置 package必须在子package前配置

         name
package名称

         extends:
继承的父package名称
         abstract:
设置package的属性为抽象的 抽象的package不能定义action true:false
         namespace:
定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为
http://localhost:8080/struts2/test/XX.action
     -->

()

 

 

Web.xml文件:

首先要包含:<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"

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

       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

       http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

 

首先:增加一个过滤器

       <filter>

              <filter-name>struts2</filter-name>

              <filter-class>

                     org.apache.struts2.dispatcher.FilterDispatcher

              </filter-class>

       </filter>

 

       <filter-mapping>

              <filter-name>struts2</filter-name>

              <url-pattern>/*</url-pattern>

       </filter-mapping>

注意:中文乱码问题的解决:主要是mysql设置字符集为utf-8,jsp网页设置成uft-8就行了。剩下的工作就可以交给这个过滤器来完成.

这个是filterstruts2自带的过滤器类,注意不要写错。是在程序一运行就会加载的,所以书写filter 的时候要非常小心,一错程序就不能正常运行了。org.apache.struts2.dispatcher.FilterDispatcher这个就是自带的过滤器类。

 

       <listener>

              <listener-class>

                     org.springframework.web.context.ContextLoaderListener

              </listener-class>

       </listener>

这里主要是使struts增加对spring插件的支持。这样的话就可以用spring来管理action了。以后一切有关操作(包括配置数据源,actionservice等等),都交由spring来办理.

 

applicationContext.xml文件:

首先添加xsd,标签库的支持:

       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.0.xsd">

这样的话,就可以使用提示,添加种bean.

先介绍一下datasource.也就是配置数据源.

<bean id="dataSource"

class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

       <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

       <property name="url" value="jdbc:mysql://localhost:3306/mytest"></property>

       <property name="username" value="root"></property>

       <property name="password" value="root"></property>

       <property name="maxActive" value="100"></property>

       <property name="maxIdle" value="30"></property>

       <property name="maxWait" value="500"></property>

       <property name="defaultAutoCommit" value="true"></property>

</bean>

我们可以看到:使用apachedbcp配置的数据源,首先使用org.apache.commons.dbcp.BasicDataSource,在销毁时关闭该数据源. 然后配置driverClassName,url,username,password,maxActive,maxIdle,maxWait,defaultAutoCommit等属性.

 

<bean

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

       <property name="dataSource" ref="dataSource"></property>

       <property name="hibernateProperties">

              <props>

                     <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

                     <prop key="hibernate.show_sql">true</prop>

              </props>

       </property>

       <property name="mappingResources">

              <list>

                     <value>com/test/bean/User.hbm.xml</value>

              </list>

       </property>

这里建立一个sessionFactory,类名为org.springframework.orm.hibernate3.LocalSessionFactoryBean"

hibernateProperties:在这里,我们定义了他的两个key,hibernate.dialecthibernate.show_sql.一个是来指定sessionFactory的方言,一个在指定是否在控制台打印sql语句

mappingResources用来指定使用的实体映射文件: com/test/bean/User.hbm.xml.因为不只一个,所以要用<list></list>包裹起来。

当然还要指定:datasourc,这个datasource就是上面所定义的那个datasource.

 

<bean id="userDao" class="com.test.dao.impl.UserDAOImpl" scope="singleton">

       <property name="sessionFactory">

              <ref bean="sessionFactory"/>

       </property>

</bean>

userDao用来指定一个自定义的Dao的实现类。是一个单例的,而且具有sessionFactory的属性

<bean id="userService" class="com.test.service.impl.UserServiceImpl">

       <property name="userDao" ref="userDao"></property>

</bean>

然后将上面的那个userDao作为一个依赖注入到userSevice.以后userService就可以使用这个userDao.

<bean id="saveUserAction" class="com.test.action.user.SaveUserAction" scope="prototype">

       <property name="service" ref="userService"></property>

</bean>

<bean id="listUserAction" class="com.test.action.user.ListUserAction" scope="prototype">

       <property name="service" ref="userService"></property>

</bean>

 

<bean id="removeUserAction"

class="com.test.action.user.RemoveUserAction" scope="prototype">

       <property name="service" ref="userService"></property>

</bean>

 

<bean id="updatePUserAction"

 class="com.test.action.user.UpdatePUserAction" scope="prototype">

       <property name="service" ref="userService"></property>

</bean>

 

<bean id="updateUserAction"

class="com.test.action.user.UpdateUserAction" scope="prototype">

       <property name="service" ref="userService"></property>

</bean>

 

<bean id="generateExcelAction"

 class="com.test.action.user.GenerateExcelAction" scope="singleton">

       <property name="service" ref="userService"></property>

</bean>

下面这几个action都要使用userService,所以都依赖注入到他们当中了.

注意,我们可以看到scope=prototype/singleton.singleton表示单例,即在IOC容器生命周期中只创建一个实例。而prototype则可以创建多个实例.每次都不同而且.

()

 

前端验证:

首先申明一个xml文件:这个文件很讲究的。*Action-validation.xml

要增添dtd的支持:

 <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

注意:类名为前面是一个特定存在的对应的要处理的action.

方法一:

<validators>

       <field name="user.firstname">

              <field-validator type="requiredstring">

                     <message>required first name</message>

              </field-validator>

       </field>

       <field name="user.lastname">

              <field-validator type="requiredstring">

                     <message>required last name</message>

              </field-validator>

       </field>

       <field name="user.age">

              <field-validator type="required">

                     <message>required age</message>

              </field-validator>

              <field-validator type="int">

                     <param name="min">1</param>

                     <param name="max">150</param>

                     <message>age should be between ${min} and ${max}</message>

              </field-validator>

       </field>

      

</validators>

 

我们看到<field name=user.*></field>是一个对象点属性的。不然理解上面的。Firstnamelastname 只要求输入不为空的字符串即可.age则需要输入整型而且是1150之间的数.

 

方法二:

<validators>

       <field name="user">

              <field-validator type="visitor">

                     <param name="context">user</param>

                     <param name="appendPrefix">true</param>

                     <message>user's </message>

              </field-validator>

       </field>

</validators>

 

这里使用visitor模式.

第一个param参数, context属性值为user是对应action(UpdateUserAction)中的User类的对象,而且是必须存在的。

第二个和第三个主要是设置该属性的前缀的。为true时该前缀时会和message一并显示的前台客户端.

 

还有一个文件:一般包在和bean同一个包下,即User.hbm.xmlUser.java

       <field name="firstname">

              <field-validator type="requiredstring">

                     <message>required first name</message>

              </field-validator>

       </field>

 

       <field name="lastname">

              <field-validator type="requiredstring">

                     <message>required last name</message>

              </field-validator>

       </field>

-------------------------------------------------------------

 

       </field>

其实和之前的那个Validators差不多,只是该名字改为:firstname。而不用user.firstname.

下面讲:

DAO: userDao.java

讲接口类:UserDao,里面定义了一些接口类方法,没有提拱,为实现类作准备

       public void saveUser(User user);//保存至数据库中

       public void removeUser(User user);//从数据库删除

       public User findUserById(Integer id);//根据主键id进行查找

       public List<User> findAllUsers();//查询所有的记录,并返回到List

       public void updateUser(User user);////更新指定的记录

 

DAO实现层:UserDAOImpl.java实现接口类所有的方法且继承了HibernateDaoSupport

@SuppressWarnings(“unchecked”)

这个注解其实告诉编译器,该对应的方法不用再见编译,可直接跳过。

如出现List<User>的情况

第一个:saveUser(User user)方法

this.getHibernateTemplate().save(user);

第二个:removeUser(User user)方法

this.getHibernateTemplate().delete(user);

第三个:findUserById(Integer id)方法

User user = (User) this.getHibernateTemplate().get(User.class, id);

return user;

第四个: findAllUsers()方法

String hql = "from User user order by user.id desc";

return (List<User>)this.getHibernateTemplate().find(hql);

 

我们可以看出来,这种方式非常的简单明了,而且我们手工要写的代码很小,大大节省我们开发的时间。

 

还有一层就是服务层:专门将数据库的操作组织成一个逻辑,有一连串的数据库操作,对操作进行封装。用以提拱给Action使用.这在里只是一些简单的数据库操作,所以实现起来比较简单。但是在实际开发的项目标中我们要考虑的问题很多。所以该层必不可少.

当然:也要定义一个接口类.UserService

public List<User> findAll();

 

       public void save(User user);

       public void delete(User user);

       public User findById(Integer id);

       public void update(User user);

       public InputStream getInputStream();

这同上面的UserDAO一一对应。所以不用再解释了。

无非是再一次调用该方法了。

UserServiceImpl.java中着重讲一下。GetInputStream()方法.这里用到了POI组件的方法

和有关文件的操作.

HSSFWorkbook wb = new HSSFWorkbook();//定义一个工作薄

              HSSFSheet sheet = wb.createSheet("sheet1");//定义一个工作页

 

              HSSFRow row = sheet.createRow(0);//定义第一行

 

              HSSFCell cell = row.createCell((short) 0);//定义第一个单元格

              cell.setEncoding(HSSFCell.ENCODING_UTF_16);//中文编码

              cell.setCellValue("序号");//设置该属性值

 

              -------------------------------------------------------------------------------

 

              List<User> list = this.findAll();//从数据库中查询出数据返回到List

 

              for (int i = 0; i < list.size(); ++i)

              {

                     User user = list.get(i);//得到一个指定的User

                     row = sheet.createRow(i + 1);

 

                     cell = row.createCell((short) 0);

                     cell.setEncoding(HSSFCell.ENCODING_UTF_16);

                     cell.setCellValue(i + 1);

 

                     cell = row.createCell((short) 1);

                     cell.setEncoding(HSSFCell.ENCODING_UTF_16);

                     cell.setCellValue(user.getFirstname());

//写入数据库的记录到单元格中

                     ----------------------------------------------------------------------------

              }

 

              File file = new File("test.xls");//定义一个文件,

              try

              {

                     OutputStream os = new FileOutputStream(file);//定义一个文件输出流

                     wb.write(os);//写入到文件中

                     os.close();//关闭流

              }

              catch (Exception e)

              {

                     e.printStackTrace();//处理异常

              }

 

              InputStream is = null;//申明一个输入流

              try

              {

                     is = new FileInputStream(file);//定义

              }

              catch (FileNotFoundException e)

              {

                     e.printStackTrace();

              }

然后就可以返回出去,以拱使用return is;

Sevice中的方法最终是提拱给action使用。去实现表单特定的功能.

 

Action:

SaveUserAction.java 这个类是要继承ActionSupport的。

这样就有了execute()方法和validate()方法了。

我们主要还是用到execute()方法来处理一些业务逻辑方法的。

如:可以写入

validate()主要是做一些验证方面的事情,但前面我们已经使用了两种方法对其进行了处理,这里不再说明了。

 

 

注意:每个action都应该在struts.xmlapplicationContext.xml中注册过的。不然的话就不能正常工作而报错的。

GenerateExcelAction.java

在这里:---------------------------------------

       public InputStream getDownloadFile()

       {

              return this.service.getInputStream();

       }

      

       @Override

       public String execute() throws Exception

       {

              return SUCCESS;

       }-----------------------------------------------------

好像execute没有实现什么功能,其实这部分工作都交给getDownloadFile()来完成的。而这个方法又在service中。而配置文件又放在strtus.xml中,上面已经对此做过解释,这里不在多说.

 

国际化问题:

这里要用到几个*.properties文件.首先:struts.properties, globalMessages_zh.properties,

globalMessages_en.properties文件.

struts.properties

struts.custom.i18n.resources=globalMessages使得后面两个配置文件能够被*.jsp读取到.

 

globalMessages_en.properties

firstname=firstname

lastname=lastname

age=age

globalMessages_zh.properties

firstname=/u59D3

lastname=/u540D

age=/u5E74/u9F84

 

然后在其中一个jsp文件中Lsave.jsp

<s:textfield name="user.firstname" label="%{getText('firstname')}"></s:textfield>

就可以根据本地的IE的语言而显示不同。这样就实现了国际化

 

一些细节:在jsp中要引入标签库,:

<%@ taglib prefix="s" uri="/struts-tags"%>,这样就可以使用struts标签库了.

如果点击一下删除,能出现一个提示对话框。在这里我们利用javascript来实现之

<script type="text/javascript">

       function del()

       {

              if(confirm("你真的想删除该记录么?"))

              {

                     return true;

              }

              return false;

       }

       </script>

同时在这链接处使用才级生效.

<s:a href="deleteUser.action?user.id=%{#us.id}" onclick="return del();">delete</s:a>

注意:这里使用{#***}的方式来引用

 

us是什么呢?看<s:iterator value="#request.list" id="us">.所以是request.list的一个别名.request.list又是什么呢?

Map request = (Map) ActionContext.getContext().get("request");

request.put("list", service.findAll());

原来request是可以用来存储一些状态信息的。像sessionapplication…

记得在struts 1.2.我们使用

Session.setAttribute(list,list);来实现之.

这里使用一个Map对象来实现.

表单的形式也比较简单

    <s:form action="saveUser">

    ----------------------------------------------------

</s:form>

Webworksturts1.2共同组成strtus2