SSH框架整合
一、原理图
action:(struts2)
1、获取表单的数据
2、表单的验证,例如非空验证,email验证等
3、调用service,并把数据传递给service
Service:业务层
增删改查,比如:登录,调用dao的query方法进行查询,返回结果,进行用户名密码的比对,将结果返回给action
Dao(hibernate)save、delete、update、query
Spring
1、ioc,由spring管理创建、销毁action、service、dao
Java本身(实现接口),cglib(第三方的jar包)
2、aop,管理service的事务
二、整体结构
src根目录
1、com.jsoft.action包
2、com.jsoft.hbm.dao包:连接数据库的dao
3、com.jsoft.hbm.orm包:hibernate实体类和关系映射文件
4、com.jsoft.services.impl包:service的具体实现
5、applicationContext.xml:spring配置文件
1.配置.xsd
2.配置数据库连接池,与hibernate无关
举例子:网线
上课需要网线,来一个同学上课需要拉一根网线,陆陆续续来二十多个同学就要陆陆续续拉二十跟网线,效率低,想要提高效率就要估计要来的学生数假定为23,那么就直接事先拉30根网线,留出7根网线作备用
提出:假如没有数据库连接池,有一个用户需要做查询就需要跟数据库做一个连接,当又有一个用户做查询还要建立连接,这样做耗时长,而且非常耗费资源
当有数据库连接池时: 启动服务时就建立若干个连接,没有用户用也先放着,当有一个用户需要访问的时候就在连接池中挑一个空闲的连接给用户做增删改查的操作,以此类推,并发执行。并发执行操作时不需要和数据库建立连接,效率高。用户1完成操作后就释放连接到连接池中已备其他用户使用,用来循环使用。如果若干连接都被使用就继续建立若干个连接以供备用。
该ssh框架用的是c3p0数据库连接池,是hibernate推荐是用的。
3.配置hibernate的session工厂
Hibernate本身就有一个session工厂,而在这里我们用的是spring配
置的session工厂,为了hibernate和spring更好的集成。
第一、注入dataSource
Property中的ref属性的意思是把id=dataSource的对象1注入到2这个类的name为dataSource的成员变量3中,其中1与4对应。Ref表示注入的是对象类型,基本数据类型用value
第二、采用通配符的方式配置加载.hbm.xml的映射文件,.配置方言、显示sql、格式化sql。
4.配置事务管理器
第一、注入(同上)
第二、定义事务通知,定义方法的过滤规则,save*等表示当方法名满足save等为前缀的时候会自动加上事务。也就是说具体的service层和action层代码增删改查方法名必须以这几个为前缀,否则报错。
意思是session没有绑定事务。
第三、定义aop,表示的是事务具体加在了哪里,与过滤规则相互配合管理事务
5.启用cglib
6.把sessionFactory注入到BaseHibernateDAO的成员变量sessionFactory中
7.这里写其他的bean
=这是一条分割=========
6、struts.properties:struts2常量配置
创建.properties文件的方法是新建file,后缀为.properties
注意:struts.objectFactory=spring指的是把对象工厂指向spring,表示由spring创建对象。(与三、6相对应)
7、struts.xml:struts配置文件
<action name=””class=””>
//这里写**.jsp
WebContent根目录
8、META-INF文件夹
9、WEB-INF文件夹
1、lib文件夹:
引入的是ssh框架的jar包
【struts2版本2.3.24】【spring版本3.2.0】【hibernate版本4.2.4】
2、web.xml:
启动web容器时,spring容器也跟着启动,接着读取applicationContext里的配置文件,里面包含:指定spring配置文件的路径和名称,其中的classpath指的是src根目录下、struts2过滤器、通过监听器的方式启动spring
3、各种jsp页面
三、登录功能具体代码【web工程】
1、对于com.jsoft.hbm.orm包
创建数据库表对应的实体类Student,编写映射文件,在编写好的映射文件中修改主键生成方式为uuid.hex,以及数据库中有下划线的数据要添加下划线
2、编写视图层登录页面login.jsp
表单提交时传递的参数name属性值为username和password。记得修改两个地方编码集为utf-8和删除pageEncoding="ISO-8859-1"。如果jsp文件中第一行的<%报错,就右键WebContent选中build path的configure build path,在右侧选第四个add library,选中server runtime选next,选中tomcat点击finish。
2、在com.jsoft.services.impl包中创建LoginService类
①创建BaseHibernateDAO类的成员变量dao,并获取set方法
②编写querylogin方法
注意返回的是一个Map,因此新建一个Map对象returnMap用来存放数据和当做返回值。然后还要有表单提交来的name值为username和password的数据。然后用成员变量dao调用query方法编写hql语句并用List变量接收,判断如果不空就创建学生类对象s并获取password与表单传递过来的password值作比较,并用put方法加入到returnMap中,如果相等就设置code值为1表示登陆成功;如果不相等就设置code值为-1表示密码错误。如果list为空就设置code值为-1表示用户名密码不匹配。
3、在com.jsoft.action包中编写LoginAction类
①继承ActionSupport类
②定义成员变量username,password,还有LoginService类的成员变量loginService并获取他们的set方法
③重写excute方法
定义Map变量map,用put方法放入表单提交来的数据username,password,注意表单、aaction、sevice中的username和password要一一对应相等。用LoginService类的成员变量loginService调用querylogin方法参数为map,定义Map变量resultMap接收,判断传递过来的code值,如果是1则跳转成功页面,否则跳转登录页面。
4、配置service
在spring的配置文件applicationContext.xml中新建标签,用到id属性和类同名为LoginService,class属性写的是LoginService的路径名com.jsoft.services.impl.LoginService(建议用粘贴复制,写好之后点击检查)。在bean标签里面写标签编写注入代码,属性值为name里面写要注入的成员变量名dao,属性值ref写的是要注入id值为BaseHibernateDAO的对象。
5、配置action
同样在之后新建标签,用到id属性和类同名为LoginAction,class属性写的是LoginAction的包名加类名。在所有action配置中添加scope="prototype",表示多实例模式,一般情况,action有成员变量,采用单例模式会发生缓存上一次的纪录,所以要采用多实例模式。也就是说有成员变量就用多实例模式。
6、在struts.xml中配置action
新建标签,用到name属性和class属性,name属性写的是表单里面的action属性名login;其中class属性不能写类的全路径,而应该是spring配置文件中的的id属性值LoginAction,原因是由spring管理对象,(与二、6相对应)如果写的是类的全路径,那么在struts2中会根据全路径自己创建对象,但采用这种方式不会在这个类里面注入LoginService这个成员变量,会报的是空指针。
然后在action标签里编写标签表示结果,如果成功name属性值为success,跳转到loginSuccess.jsp;如果失败name属性值为login,跳转类型type属性值为redirect方式,跳转到login.jsp。
四、登录功能ssh框架具体执行流程
当点击提交按钮时,将请求发送给login.action,被过滤器所拦截,过滤器就知道当前访问资源是login.action,根据action这个名称会到struts.xml配置中找与之相匹配的name属性值为login的action,然后找class属性,又因为在常亮配置中有struts.objectFactory=spring这句话,知道class里面不是类的名称而是spring的id,然后会到spring容器applicationContext.xml中找id为LoginAction的bean,之后spring会自行实例化class属性里面的类,然后还会检测到要往这个类的成员变量中注入loginService这个对象,然后还会找到id为LoginService的bean,接下来还会实例化class里面的类,还会检测到要往这个类的成员变量dao中注入BaseHibernateDAO这个类,然后找到id为BaseHibernateDAO的bean,实例化class里面的类,还会检测到要往这个类的成员变量sessionFactory里注入sessionFactory。接下来会把实例化好的BaseHibernateDAO这个类的对象传递给dao这个成员变量中,接下来在把LoginService注入到loginService这个成员变量中。然后在struts.xml配置文件中才可以用LoginAction这个对象,然后把请求转交给LoginAction这个对象,然跳到LoginAction这个类。然后把相应的从表单传递过来的值放到Map中,然后调用LoginService,在里面调用dao的query方法,然后返回code值给LoginAction类,根据判断跳转到相应的页面。
如果该org.jsoft.hbn...要改下面对应的地方
五、增加功能具体代码
1、编写视图层增加页面addStudent.jsp
表单提交时传递的参数name属性值为student.name和student.age。其他同上。
2、com.jsoft.services.impl包,创建StudentService类
①创建BaseHibernateDAO类的成员变量dao,并获取set方法
②编写增加方法save【注意方法名要遵守事务规则】
注意形参类型为Student,然后用dao调用BaseHibernateDAO类中的save方法传递参数为刚才的形参student,返回的是一个Serializable【序列化的接口,基本数据类型,字符串等等一些类都实现这个接口,一会返回的时候可以把它强转为字符串这个字符串就是主键】,也就是id,【因为之前设置的主键生成方式为uuid,返回的不知道是什么,hibernate为了让我们知道,做保存时返回一个字符串的对象】,强转并输出id。
3、在com.jsoft.action包中编写AddStudentAction类
①继承ActionSupport类
②创建Student类对象student【因为表单传递过来的是对象类型,所以要有get方法】,定义StudentService类的成员变量studentService并获取他们的set方法
③重写excute方法
用studentService调用save方法传递参数为student
4、配置service
5、配置action
6、在struts.xml中配置action
六、查询功能具体代码
1、在com.jsoft.services.impl包中的StudentService类中添加查询方法query【注意方法名要遵守事务规则】
注意返回的是一个Map,因此新建一个Map对象returnMap用来存放数据和当做返回值。用dao调用query方法,第一个参数是编写hql语句,此处为from Student,第二个参数是查询条件,此处做简单查询返回null,返回值是List类型,定义list变量接收。然后把结果放到returnMap中,最后返回returnMap。
2、在com.jsoft.action包中编写ShowStudentAction类
①继承ActionSupport类
②定义StudentService成员变量studentService并获得set方法
③重写excute方法
在里面用studentService这个成员变量调用query方法传递参数为null,定义Map类型的变量resultMap用来接收,再用resultMap调用get方法,里面的字符串类型的k值必须和上面put的k值一样是list,然后用List类型的变量list接收,强转list。接下来把list穿传回到结果页面中,定义List类型的成员变量list,并且要有get方法,把之前定义的List局部变量删除。
3、配置service【用上面配置的就可以】
4、配置action
5、在struts.xml中配置action
6、创建显示结果jsp:showStudentList.jsp【用到jstl和el表达式】
引入jstl标签库:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
Table标签里面首先写一个tr若干个td,分别表示编号姓名年龄,之后调用c标签的forEach方法,里面添加items属性获取到list,添加var属性里面写item,添加varStatus属性定义变量名vs,在后面调用时用vs.count显示对应序号。
之后复制之前写的trtd到forEach里面,用item分别点出相应的属性
七、查询功能运行流程:
首先访问showStudentList这个action,才能到达列表页面,然后将这个请求发送到ShowStudentAction这个action中然后调用StudentService的query方法,在里面执行查询,结果返回到action中,在action中在吧这个成员变量取出来放到list中,又因为有get方法所以将这个数据传递到jsp里,然后显示页面。注意直接访问jsp没有用,因为没有进入到action,也就没调用service进行查询,就不会有相应的结果。
八、删除功能具体代码
1、在com.jsoft.services.impl的StudentService类中编写通过id删除的方法deleteById
返回值类型是int,形参为String,String变量名为id,用dao调用update方法,里面的第一个属性写hql语句,第二个属性为String类型的id,将整个结果返回。
2、com.jsoft.action包,写DeleteStudentByIdAction类
①继承ActionSupport类
②定义StudentService成员变量studentService和Student类成员变量id并获得相应的set方法
③重写excute方法
用studentService调用deleteById这个方法,参数传递id
3、在applicationContext.xml中配置service【因为之前已经配置好了,所以不用配置】和action【注意把action配置成多实例模式scope="prototype"】
4、配置struts.xml
6、在showStudentList.jsp页面里编写
首先添加一个td,写操作,然后在c标签里用a标签写修改和删除
<a href="javascript:void(0)"onclick="deleteById('${item.id }')">删除 然后写script标签,用function定义方法deleteById,参数传递为id,用if添加一个判断条件为confirm,里面内容写的是:location.href = "deleteStudentById.action?id=" + id
九、修改功能具体代码
1、在org.jsoft.services.impl中的StudentService类中添加通过传过来的id查询的方法queryById
返回值类型是Student,形参为String,String变量名为id,用dao调用getById方法,里面的第一个属性写Student.class,第二个属性为id,【注意这个id不用加双引号】将整个结果返回。
2、org.jsoft.actions包中创建ShowStudentByIdAction类
①继承ActionSupport类
②创建私有的成员变量并获取相应的get和set方法:String类型的变量id,Student类型的s,StudentService类型的studentService
③重写excute方法
用studentService调用queryById方法,传入参数为id【注意:此处的id也不是字符串类型的】,用Student对象s接收
3、在applicationContext.xml中配置service【上面配置过了所以不用配置】和action【注意把action配置成多实例模式scope="prototype"】
4、配置struts.xml中配置ShowStudentByIdAction
成功之后跳转到回显页面showStudentById.jsp
5、在showStudentList.jsp中的修改部分添加超链接:
修改
【意思是点击修改时跳转到action名为showStudentById的struts.xml中】
6、编写回显页面showStudentById.jsp
和添加页面相似,复制粘贴,在form表单中添加属性method以post方式提交,在input标签中添加传入的id,然后分别在后面添加value属性,里面写EL表达式用在ShowStudentByIdAction类中创建的Student成员变量s调用student的具体属性,注意在这个类中必须用s接收,即s=XXX,然后把添加按钮改成修改,最后把表单提交到updateStudent.action。
【现在已经通过id查询到要修改的字段了,接下来要真正执行修改操作了】
7、在org.jsoft.services.impl中的StudentService类中添加通过传过来的id查询的方法update
返回值类型为void,参数类型为Student参数为student,用dao调用update方法,参数为刚创建的student。
8、在org.jsoft.actions包中创建UpdateStudentAction类
①继承ActionSupport类
②创建私有的成员变量:Student类实例对象student【new】,StudentService类的对象studentService
③重写excute方法
用studentService调用update方法,参数为刚创建的student
9、在applicationContext.xml中配置service【上面配置过了所以不用配置】和action【注意把action配置成多实例模式scope="prototype"】
10、配置struts.xml中配置UpdateStudentAction
成功之后跳转到之前的展示页面showStudentList.jsp
注意在result标签中修改跳转类型为type="redirect"
十、修改功能运行流程:
【大概流程是先查询到要修改一列对应的id,跳转到回显页面进行修改,修改之后再跳回到之前的展示页面】具体如下:
在展示页面的对应行中点击修改按钮后,获取到id值,并访问showStudentById.action,也就是在struts.xml配置中找到action名为showStudentById的部分,运行到class属性时找到id名为ShowStudentByIdAction的applicationContext.xml配置中的bean标签对应部分,进入到class路径下的org.jsoft.actions.ShowStudentByIdAction中,在这个类中定义String类型的变量id存刚才从链接传入的id,将查询出来的结果封装到Student类型变量s中,编写回显页面showStudentById.jsp,用EL表达式调用刚才封装到s中的各种要修改的属性并进行相应的修改【注意还要传递一个id,因为是根据id修改,如果不传递id报错如下:】
最后以post方式提交到updateStudent.action,,也就是在struts.xml配置中找到action名为updateStudent的部分,运行到class属性时找到id名为UpdateStudentAction的applicationContext.xml配置中的bean标签对应部分,进入到class路径下的org.jsoft.actions.UpdateStudentAction中,在这个类中创建Student实例对象student,将修改好的数据封装到里面,用studentService对象调用编写的update方法把修改的数据写入数据库,之后回到applicationContext.xml中,将studentService注入到StudentService中,最后回到struts.xml中通过重定向的方式type="redirect"跳转到结果展示页面showStudentList.action展示出修改的结果。