用SSH2简单实现了用户注册登录删除功能第一次尝试把SSH2整合起来,这里记下编写当中遇到的问题和自己的思考
用SSH2简单实现了用户注册登录删除功能
第一次尝试把SSH2整合起来,这里记下编写当中遇到的问题和自己的思考
一、使用struts编写登陆注册等界面
<body> This is my Register page. <br> <form action = "register!register" method = "post"> username:<s:textfield name ="username"/><br> password:<s:password name = "password1"/><br> repeatpassword:<s:password name = "password2"/><br> email:<s:textfield name ="email"/><br> <s:submit value ="submit"/><br> <s:reset value ="reset"/><br> <s:actionerror /> <s:actionmessage /> </form> </body>
注意这里的 <s:actionerror /> <s:actionmessage />用法表示出Action中的this.addActionError("the username repeated");字符串参数。
由于之前分析过很多类似的界面,这里不再赘述
二、在spring框架中引入hibernate框架
首先我引入spring框架,在其配置文件中,引入hibernate框架。
(一)那么我们必须配置数据源,那么什么是数据源呢?我的理解是数据源就是软件与数据库连接的一个桥梁,我们在其配置中输入一些用户名密码等信息,通过它,我们连接到数据库中。这里,有两个数据源可以供我们使用,一个是apache的DBCP包下的BasicDataSource,一个是hibernate的c3p0,这两者的区别
是C3P0中的配置可以更加的丰富。详情可以参见http://weizuqing1986-126-com.iteye.com/blog/812748或者http://www.blogjava.net/sealyu/archive/2010/02/02/311728.aspx。这里我们选用C3P0。注意如果选用BasicDataSource,则
要引入commons-dbcp.jar、commons-pool.jar包
<bean id = "dataSource"class = "com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass"><value>com.mysql.jdbc.Driver</value></property><property name="jdbcUrl"><value>jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=gbk</value></property><property name = "user"><value>root</value></property><property name = "password"><value>root</value></property><property name="maxPoolSize"><value>20</value></property><property name="minPoolSize"><value>2</value></property><property name="initialPoolSize"><value>3</value></property><property name="maxIdleTime"><value>60</value></property></bean>
(二)引入sessionFactory的配置,这里的sessionFactory就是Hibernate框架中的SessionFactory,那么它要完成那些任务呢,首先它是数据源的代理,并加载映射文件,注意映射文件我们一般放在com.项目名.ORM包的下面,此外还要完成加载hibernate配置信息的任务。
<bean id = "sessionFactory"class = "org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name = "dataSource" ref = "dataSource"/><property name = "mappingResources"><list><value></value><value>com/SSH2/ORM/User.hbm.xml</value></list></property><property name = "hibernateProperties"><props><prop key = "hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key = "show_sql">true</prop><prop key ="hibernate.jdbc.batch_size">50</prop></props></property></bean>
(三)事物管理器和事物拦截器的配置
在spring的配置文件中配置了一个hibernate的事务管理器,这个管理器只是管理sessionFactory中的事务(不包括事务的声明,提交和回滚)。在spring的配置文件中配置了一个spring事务拦截器,比如 <propkey="get*">PROPARAGATION_REQUIRED,readOnly</prop>这个就是拦截以get开头的数据库请求,它会自动为你的get*请求就加上事务控制,成功则提交,失败则回滚(hibernate的事务管理器没这功能)。
在spring的配置文件中配置了一个hibernate的事务管理器,是为了注入给事务拦截器,这句就是注入的配置
<property name="transactionManager" ref="transactionManager" />
拦截器详见[url]http://blog.163.com/yangyanninhao@126/blog/static/239900292007101852517691/ [/url]
各种事物管理器,详见http://1985wanggang.blog.163.com/blog/static/776383320088995020502/
<bean id = "transactionManager" class = "org.springframework.orm.hibernate3.HibernateTransactionManager"><property name = "sessionFactory" ref = "sessionFactory"/></bean><bean id = "transactionInterceptor" class = "org.springframework.transaction.interceptor.TransactionInterceptor"><property name = "transactionManager" ref = "transactionManager"/><property name = "transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean>
三、spring框架中引入struts框架
(一)引入相应的struts所需要的包并在spring的配置文件中配置struts
1.引入所需要的相应的包,在Spring配置文件中装配struts2的Action实例
比如:
<bean id = "userDao" class = "com.SSH2.dao.UserDao"><property name = "sessionFactory"><ref local = "sessionFactory"/></property></bean><bean name = "LoginAction" class = "com.SSH2.action.LoginAction"><property name = "userDao" ref = "userDao"/></bean><bean name = "RegisterAction" class = "com.SSH2.action.RegisterAction"><property name = "userDao" ref = "userDao"/></bean>
这里一定要注意userDao这个类继承自HibernateDaoSupport,那么它就一定要注入SessionFactory,因为HibernateDaoSupport需要用到SessionFactory。同时注意<ref local>和<ref bean>的用法
形式一: <ref bean= "mybean "/>
通过该标签可以引用同一容器或父容器内的任何bean(无论是否在同一xml文件中),XML ‘bean’元素的值即可以是指定bean的id值也可以是其name的值
形式二: <ref local= "mybean "/>
它可以用XML解析器来验证所引用的bean是否存在同一文件中,local属性值必须为目标bean的id属性值;如果在同一配置文件中没有找到引用的bean,xml解析器将抛出一个异常 。
2.然后在struts.xml中就可以引入这个Action
<action name = "login" class ="LoginAction"><result name = "success">welcome.jsp</result><result name = "input">login.jsp</result></action>
3.在struts.xml中配置struts.objectFactory
<!-- 设置Struts2默认的ObjectFactory为spring --><constant name="struts.objectFactory" value="spring" />
那么这个objectFactory有什么用呢
这个属性用于说明Struts2的 对象池创建工厂,Struts2也有自己的对象池,就像Spring那样,在配置文件中你可以引用对象池中的对象,你可以借助于Spring中的对象池,当想要得到Spring中的对象池时,申明struts.objectFactory为Spring的对象池构建工厂.
详见http://blog.sina.com.cn/s/blog_8f880c5e01011lij.html
四、编写检查用户名是否存在,如果存在就显示错误信息,如果不存在就插入到数据库中
(一)通过hibernate逆向工程生成映射文件
1.这里一定要注意必须向引入Hibernate框架,才能对该项目使用逆向工程,我们可以在spring的基础上引入hibernate框架,只不过hibernate配置文件选择applicationContext,并且不生成SessionFactory,而是给出SessionFactory的id。
(二)在在RegisterAction中通过isExist函数判断数据库中是否有重复的名字
public String register(){if(getUserDao().isExist(username)){this.addActionError("the username repeated");return INPUT;}else{User user = new User();user.setUsername(username);user.setPassword(password1);user.setEmail(email);getUserDao().insertUser(user);return SUCCESS;}}
(三)函数调用UserDao中的验证方法
1.UserDao是继承自HibernateDaoSupport
public boolean isExist(final String username){List list = (List)getHibernateTemplate().execute(new HibernateCallback(){public Object doInHibernate(Session session){List result = session.createCriteria(User.class).add(Restrictions.eq("username", username)).list();return result;}});if(list.size()>0){return true;}else{return false;}}
2、Criteria是一种更加面向对象的查询语言
3、Criteria criteria = session.createCriteria(User.class)是根据给定的映射类生成相应的criteria对象。
而
criteria.add(Restrictions.eq("username", username))
注意是判断username这个属性名字给定的属性值和username这个变量所代表的值是否相同。
4.这里要注意方法类的内部类,不能访问该方法的局部变量,除非是final型的,因为方法执行完毕后,方法内的属性也会随之销毁
(四)把用户信息插入到数据库中
public void insertUser(User user){getHibernateTemplate().saveOrUpdate(user);}
这里就是hibernateTemplate的简单用法
五、登陆到欢迎界面
(一)在loginAction中调用execute
public String execute(){if(getUserDao().isValid(username, password)){ActionContext.getContext().getSession().put("username", username);return SUCCESS;}else{this.addActionError("login failed");return INPUT;}}
(二)在UserDao中完成用户名的验证
public boolean isValid(final String username,final String password){List list = (List)getHibernateTemplate().execute(new HibernateCallback(){public Object doInHibernate(Session session){List result = session.createCriteria(User.class).add(Restrictions.eq("username", username)).add(Restrictions.eq("password", password)).list();return result;}});if(list.size()>0){return true;}else{return false;}}
六、在web.xml中配置启动信息
(一)指定applicationContext所处的位置
<context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext.xml</param-value></context-param>
加载相应路径的applicationContext.xml不指定的话就会默认加载/WEB-INF/applicationContext.xml
(二)指定监听器
<!-- 指定以Listener方式启动Spring容器 --><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
在配置时出现了 org.dom4j.DocumentException: Error on line 1 of document : Content is not allowed in prolog. Nested
exception: Content is not allowed in prolog.
解决方法详见http://easonfans.iteye.com/blog/770217
七、删除用户功能
http://www.linuxso.com/architecture/28482.html
七删除已注册的用户
1.首先在欢迎界面中编写一个URL,这个URL就是一个删除数据库中用户的请求。特别要注意因为这个请求不是服务器自动跳转的,而是客户端发出的请求,所以实现删除功能的Action类和实现注册、登陆等功能的Action并没有使用相同的值栈,这样我们就必须把要删除的用户的名字传给Action类,那么如果传递呢?第一种可以在登陆时将用户名放在Session中,这样在DeleteAction中,我们可以使用
username = (String)ActionContext.getContext().getSession().get("username");
得到用户名。第二种方式就是在产生删除请求的URL中,我们加上一个用户名的参数。
<a href = "<s:url action = "delete!delete" ><s:param name = "username"><s:property value = "username"/> </s:param></s:url>" >删除</a><br>
这里要理解下为什么可以这样做,我们知道如果我们在表单中填写数据,在提交请求时就会将这些表单中的数据通过相应的设置方法赋值给Action或是Bean,而实际上我想我们可以理解为把请求参数赋值给相应Action或是Bean,而不仅仅是通过表单传递。
2.通过用户名调用相应函数得到表示该用户的对象
public User getUser(final String username){User user = (User)getHibernateTemplate().execute(new HibernateCallback(){public Object doInHibernate(Session session){ User user =(User)session.createCriteria(User.class).add(Restrictions.eq("username", username)).uniqueResult();return user;} }); return user;}3.删除该用户
getUserDao().delete(user);public void delete(User user){getHibernateTemplate().delete(user);}
总结:struts2,spring,hibernate如何集成
一、spring2.5集成Hibernate3.2
1.spring2.5配置文件中的配置C3P0数据源
2.我们不需要再Hibernate的配置文件中配置数据库的连接,而是把配置的内容放到spring的配置文件中。
3.我们同样在spring的配置文件中配置hibernate的sessionFactory。
4.在spring配置文件中配置hibernate的事务管理器和事物拦截器。
5.定义BeanNameAutoProxyCreator进行spring的事物处理。
6.在DAO组件中继承HibernateDaoSupport调用Hibernate3.2,通过继承HibernateDaoSupport,得到hibernate的操作模板,这个模板就是为了简化hibernate的操作。我们就可以通过继承这个HibernateDaoSupport来实现统一数据访问的接口。
二、把spring2.5集成到Struts2框架中
1.第一步:将Struts2自带的Spring插件(struts2-spring-plugin-2.0.11.1.jar)及Spring框架所依赖的JAR包(spring.jar,common-annotations.jsr,commons-logging.jar)复制到WEB-INF/lib文件夹中。
2.第二步:web.xml文件中正确配置Spring2.5
3.第三步:在struts2的配置文件中struts.xml中将对象工厂ObjectFactory设置为spring:
<constant name = "struts.objectFactory" value = "spring">
4.第四步:在Spring配置文件中装配struts2的Action实例,由于struts2在处理请求时,每个不同的请求均会产生一个相应的Action实例负责处理,因此,在配置时需要使用原型模式,以确保每次生成的是全新的Action实例。如:<bean id = "adminAction" class = "com.eportal.struts.action.AdminAction" scope = "prototype"><property name = "service" ref = "adminService"/></bean>
5.在Struts2的配置文件struts.xml中配置Action映射时,class属性不再使用类全名,而应该使用Spring配置文件中定义的相应bean实例名称。<action name ="updateAdmin" class = "adminAction">