东北大学软件学院实践考核类课程(四)实验报告11.系统分析与设计1.1系统功能描述本系统是个非常简单的注册、登录系统。本系统的实现是基于Struts2、Spring、Hibernate三个框架,系统功能单一,业务逻辑简单。当用户注册信用户时,就是向系统中增加一个新用户,对应的数据库增加一条记录。当用户输入注册信息时,系统提供了基本的输入验证判断用户输入是否合法,只有当用户输入满足基本输入要求时,才会被提交到实际的登录系统,进行实际的登录处理。系统还使用了随机产生的图形验证码来防止刷新,防止用户通过单击浏览器的书安心按钮来重复注册多个用户。系统还提供了一种Ajax方式来验证用户输入的注册名是否有效,系统要求所有的用户名不能重复。故当用户输完用户名后,系统立即在页面上方提示用户该用户名是否可用,如果系统中没有该用户名,则系统提示该用户名可用;否则提示用户该用户名重复,用户必须重新选择用户名注册。当用户注册一个新用户名之后,就可以使用系统的登录功能来登录系统了,用户输入登录用的用户名、密码后,系统一样提供了基本的输入校验。除此之外,系统还采用了随机产生图形验证码来防止恶意用户的暴力破解,系统随机生成一个图形验证码,而用户登录必须输入图形验证码中显示的字符串,只有用户输入的字符串和系统随机生成的验证码字符相同时,系统才允许用户登录。1.2系统功能流程处理用户注册的流程图提交注册请求输入校验失败(inputresult)登录成功注册失败(failureresult)Regist.jspsuccess.jspRegist.action东北大学软件学院实践考核类课程(四)实验报告2提交登录请求输入校验失败(inputresult)登录成功登录失败(failureresult)1.3数据库设计相关的映射文件:hibernate-mappingpackage=org.reg_login.modelclassname=Usertable=user_tableidname=idcolumn=user_idgeneratorclass=identity//idpropertyname=usercolumn=user_namenot-null=truelength=50unique=true/propertyname=passcolumn=user_passnot-null=truelength=50/propertyname=emaillength=100//class/hibernate-mapping一旦提供了上面的映射文件,Hibernate就可以理解User和user_table之间的对应关系。2.系统实现与测试2.1系统采用的关键技术MVC框架采用了Struts2框架,Struts2框架的易用性,极好的简化了系统的MVC层的实现;本系统使用了Struts2的JSON插件来完成Ajax功能,除此之外本系统为了避免进行底层的Ajax交互,还是用了一个简单Prototype.js函数库,用以简化Ajax编程。Struts2框架的稳定性,为系统的稳定运行提供了保证。将User映射到user_table数据表使用ID元素来映射标识属性并指定主键生成器策略映射User类其他属性success.jsplogin.jsplogin.action东北大学软件学院实践考核类课程(四)实验报告3Spring容器作为系统的Ioc容器,将系统中所有组件都放在Spring容器中进行管理,并且充分利用了SpringIoc容器的功能,采用依赖注入来管理系统中各组件的依赖关系,避免了各组件之间的硬编码耦合,提高了系统的可扩展性。借助HibernateORM框架实现系统的持久化,通过Hibernate的框架帮助,允许上层程序采用面向对象的方式编程,二Hibernate负责把面向对象的持久化操作转换成JDBC操作,但Hibernate的底层操作对开发者完全透明,从而让用户从具体的JDBC访问中释放出来,无需理会底层的JDBC数据库访问,而是以面向对象的方式进行持久化操作。2.2关键程序流程以注册为例说明:加载类(FilterDispatcher)读取配置(struts配置文件中的Regist.Action)派发请求(客户端发送请求)调用Action(FilterDispatcher从struts配置文件中读取与之相对应的Action)启用拦截器(WebWork拦截器链自动对请求应用通用功能)处理业务(回调RegistAction的execute()方法)返回响应(通过execute方法将信息返回到FilterDispatcher)查找响应(FilterDispatcher根据配置查找响应的是什么信息如:SUCCESS、ERROER,将跳转到哪个jsp页面)响应用户(jsp---客户浏览器端显示)2.3关键代码分析Regist.action的execute方法publicStringexecute()throwsException{Mapsession=ActionContext.getContext().getSession();Stringver2=(String)session.get(rand);session.put(rand,null);if(vercode.equals(ver2)){if(mgr.addUser(user,pass,email)0){returnSUCCESS;}else{addActionError(注册失败,请重试!);returnfailure;}}else{取出Action在执行时需要用到的对象调用业务逻辑层的添加用户的方法获取随机验证码东北大学软件学院实践考核类课程(四)实验报告4addActionError(验证码不匹配,请重新输入);}returnfailure;}业务逻辑层:publicintaddUser(Stringuser,Stringpass,Stringemail)throwsException{try{Useru=newUser();u.setUser(user);u.setPass(pass);u.setEmail(email);userDao.save(u);returnu.getId();}catch(Exceptione){e.printStackTrace();thrownewException(新增用户时出现异常);}}publicvoidsave(Useruser){getHibernateTemplate().save(user);}SessionFactory是Hibernate的持久化操作的基础对象,是整个数据库经过编辑后的内存镜像,通常对应一个底层数据库。进行Hibernate的持久化操作前,必须先完成SessionFactory的初始化。本系统通过Spring容器管理SessionFactory,从而允许开发人员无需手动管理Hibernate的SessionFactory。代码如下:beanid=sessionFactoryclass=org.springframework.orm.hibernate3.LocalSessionFactoryBeanpropertyname=dataSourceref=dataSource/propertyname=mappingResourceslistvalueUser.hbm.xml/value/list/propertypropertyname=hibernatePropertiespropspropkey=hibernate.dialectorg.hibernate.dialect.MySQLDialect/proppropkey=show_sqltrue/proppropkey=hibernate.hbm2ddl.autoupdate/prop调用DAO层的save方法,将用户存储到数据库中因使用MySQL数据库,故使用MySQL方言Hibernate的映射文件东北大学软件学院实践考核类课程(四)实验报告5propkey=hibernate.jdbc.batch_size20/prop/props/property/beanDAO组件是基于Hibernate的持久化操作的,因此必须获得SessionFactory的引用才可以进行持久化操作。由于系统的DAO组件将由Spring容器来管理,而且系统的SessionFactory也是由Spring的容器来管理,因此DAO组件无需显示去的SessionFactory的引用,而是接受Spring容器注入即可。配置如下:beanid=userDaoclass=org.reg_login.dao.hibernate.UserDaoHibernatepropertyname=sessionFactoryref=sessionFactory//bean配置业务逻辑组件所依赖的DAO组件。代码如下:beanid=mgrclass=org.reg_login.service.impl.UserManagerImplpropertyname=userDaoref=userDao//bean在Spring容器中配置了业务逻辑组件后,还必须为业务逻辑方法增加事物控制。因为用户的业务逻辑方法对应用户的一次业务请求,通常而言,用户的每次业务请求都是逻辑不可分的,一次应该为该方法增加事物控制。本系统采用Spring的BeanNameAutoProxyCreator后处理器完成。代码如下:beanid=transactionManagerclass=org.springframework.orm.hibernate3.HibernateTransactionManagerpropertyname=sessionFactoryref=sessionFactory//beanbeanid=transactionInterceptorclass=org.springframework.transaction.interceptor.TransactionInterceptorpropertyname=transactionManagerref=transactionManager/propertyname=transactionAttributespropspropkey=get*PROPAGATION_REQUIRED,readOnly/proppropkey=*PROPAGATION_REQUIRED/prop/props/property/bean为业务逻辑组件注入SessionFactory引用配置事物拦截器Bean为事物拦截器Bean依赖注入一个事务管理器定义事物传播属性东北大学软件学院实践考核类课程(四)实验报告6beanclass=org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreatorpropertyname=beanNameslistvaluemgr/value/list/propertypropertyname=interceptorNameslistvaluetransactionInterceptor/value/list/property/bean由于Struts2的Action也是由Spring容器负责管理,因此,必须保证Spring容器在Web应用初始化时立即创建。代码如下:listenerlistener-classorg.springframework.web.context.ContextLoaderListener/lis