《第07章__Struts_2综合应用实例》由会员分享,可在线阅读,更多相关《第07章__Struts_2综合应用实例(47页珍藏版)》请在金锄头文库上搜索。
1、第第07章章_Struts_2综综合应用实例合应用实例第第7章章 Struts 2综合应用实例综合应用实例这里只介绍图书管理系统的两个功能:读者借书和图书管理,它已经包含了操作数据库的主要内容,其他功能读者可以根据所学知识自行完成。本系统运行时的初始主界面如图7.1所示。图7.1运行主界面第第7章章 Struts 2综合应用实例综合应用实例在没“登录”之前,操作功能的图片是灰色的,不能被单击。而当登录成功后,操作功能的图片就亮起来,登录的输入框及“登录”按钮被置灰,表示不可再进行“登录”操作。登录有两种角色,使用“管理员”登录名登录,操作功能所有图片都会亮,表示所有操作都可以进行,如图7.2所
2、示。图7.2管理员身份登录后的界面第第7章章 Struts 2综合应用实例综合应用实例如果是“学生”登录,登录成功后,前面两个图片会亮,表示可以进行操作,后面的图片还是灰色的,表示不能操作,如图7.3所示。图7.3学生身份登录后的界面7.1 建立项目建立项目首先,在MyEclipse中建立项目Struts2_Example,加载Struts2所需的5个类库、SQLServer所需的类库及文件上传所需的两个类库(这两个类库在Struts2的文件上传部分已经讲解)。然后修改web.xml文件,在第一个Struts2的例子中已经给出,不再赘述。接着在src下创建Struts2的核心配置文件strut
3、s.xml,并编写其框架代码:./此处以后添加action配置7.2 运行主界面的实现运行主界面的实现上面已经展示了初始系统的主页面,文件名为index.jsp,要实现这个功能,采用表格方式把页面分成3行1列。其中,第1行是页面的头部,由于比较复杂,进行专门设计,文件名为head.jsp。结构分布如下所示: head.jsp index.jsp7.2 运行主界面的实现运行主界面的实现为了设计图书管理系统上部页面,可以先采用Adobe公司的Photoshop或者Illustrator软件设计出整幅图页面,如图7.4所示。图7.4上部页面整幅图然后采用Photoshop或者Illustrator或
4、者FireWorks(建议采用)的图片“切片”工具,进行切片分隔,切片后如图7.5所示。图7.5切片分隔后7.2 运行主界面的实现运行主界面的实现选择“导出”功能,设置导出为“HTML和图像”;选择“选项”,对表格进行设置,如图7.6所示。图7.6 导出设置7.2 运行主界面的实现运行主界面的实现进行“导出”操作后生成的图片文件如图7.7所示。图7.7生成的图片文件7.2 运行主界面的实现运行主界面的实现同时,对系统自动生成的HTML文件进行如下处理:删除注释及img标记中对本例没有用的属性;为了HTML代码阅读方便,把系统生成的有关的图片文件改名;加入系统登录和图片对应功能的超链接代码;把扩
5、展名改成“head.jsp”。修改后的head.jsp代码。除了上面介绍的切割图片的方法外,HTML还提供了在图片上制作热点区域的方法,就是可以在一幅完整的图片上面,制作出一块区域用于超链接,该区域是用坐标来实现的。应用这种方法,只需将上面所说的头部的图片切割成上下两部分,如图7.8所示。图7.8 头部图片切割情况7.2 运行主界面的实现运行主界面的实现然后,把上面一幅图作为背景,而下面一幅图作为插入在表格中的图片,该图片可以制作热点区域来实现图片的超链接。制作完成后代码。头部实现后,运行的主界面就简单了,index.jsp代码实现为。7.3 实现实现“登录登录”功能功能由于登录时要对数据库进
6、行查询,故在编写“登录功能”的代码之前,要先编写连接数据库的代码。连接数据库的文件DBConn.java代码实现为。可以看出,数据库的连接与关闭使用的是静态方法,要对数据库连接或关闭,只需用“类名.方法名”即可。登录页面在“index.jsp”中已经包含,可以看出,当单击“提交”时,交给了“login.action”,故需要在“struts.xml”中配置该action来处理请求:/index.jsp/index.jsp7.3 实现实现“登录登录”功能功能处理请求的Action类LoginAction.java代码为。该Action中应用了模型传值,Login.java代码为:packageo
7、rg.model;publicclassLoginprivateintid;privateStringname;privateStringpassword;privatebooleanrole;/省略上述属性的get和set方法在Action中引用了LoginDao.java,该类负责登录信息与数据库的交互。DAO即为数据访问对象,在一般的项目开发中都会有DAO的存在,这样便于维护,所以,登录信息与数据库的交互由LoginDao来处理。LoginDao这样的命名方式可以使程序员根据该名称就清楚它的功能,同时可以方便地找到它。LoginDao.java代码实现。7.4 实现实现“借书借书”功能功
8、能当用管理员身份“登录”后,“图片”链接就可用了,单击“借书”,出现如图7.9所示的界面。图7.9 借书界面7.4 实现实现“借书借书”功能功能要实现这个功能,采用表格方式把页面分成3行2列。其中,第1行与第3行占两列,然后在第2行的两列中分别放两个表格,左边的表格非常简单,不多介绍了,关键是右边的表格,右边的表格又分为3行1列,第1行是“图书信息”字样及一个简单的表单,第2行中又插入了一个表格,这个表格显示图书的信息,第3行是分页的信息。基本结构如下所示:lend.jsplend.jsp7.4 实现实现“借书借书”功能功能从该页面可以看出,左边是“查询”功能,输入借书证号后,单击“查询”按钮
9、,就可以查出该借书证号的读者借了哪些书籍,而刚进入页面时,借书功能是不可用的,但当输入了借书证号后,单击“查询”按钮,会在右边显示该读者所借书籍,同时“借书”功能变亮,表示可以进行借书操作了,如图7.10所示。图7.10 查询借书信息7.4 实现实现“借书借书”功能功能输入正确的ISBN及图书ID,单击“借书”按钮,就可以借得此书,如图7.11所示。图7.11 借书成功页面7.4.1 查询已借图书查询已借图书单击“借书”链接后,出现了图7.4的界面供用户操作,从head.jsp中的代码:可以看出,单击该操作,提交到“lend.jsp”,故图7.4所示的页面的代码实现应该为lend.jsp:读者
10、可能会感觉这么长的代码怎么看,其实代码非常简单,总体来说就四个部分,第一部分:7.4.1 查询已借图书查询已借图书导入头部,具体内容前面已经讲解,不再赘述。第二部分就是页面左边的查询功能部分:内容选择借书证号:7.4.1 查询已借图书查询已借图书当输入正确的借书证号,单击“查询”时,提交到“selectBook.action”,根据struts.xml配置下面的代码:/lend.jsp处理的Action为LendAction中的selectAllLend方法,LendAction.java的该部分代码。7.4.1 查询已借图书查询已借图书由于用到了模型传值,而且在后面的与数据库交互时把查询的数
11、据记录都转化为该类中的属性,故模型代码Lend.java为:packageorg.model;importjava.util.Date;publicclassLendprivateStringbookId;privateStringreaderId;privateStringbookName;privateStringpublisher;privatefloatprice;privateStringISBN;privateDatelTime;/生成上述属性的get和set方法7.4.1 查询已借图书查询已借图书该Action中应用了3个其他类,有StudentDao、LendDao及Pager
12、,Dao是用来和数据库交互的,该Action类中应用了StudentDao的“selectByReaderId”方法。该方法是用来根据借书证号,查询学生信息,如果有该学生信息就查询该学生已借图书;如果没有就添加“不存在该学生”的信息到“message”,然后返回到页面,页面会输出该信息,告知用户输入了错误的借书证号。StudentDao.java的代码实现为。7.4.1 查询已借图书查询已借图书该Dao中的方法selectByReaderId的作用就是根据借书证号,查询学生信息;如果有就返回该学生,如果没有就返回null。当然,在应用Student类之前要先编写该类的代码,Student.ja
13、va就是student表对应的模型:packageorg.model;importjava.util.Date;publicclassStudentprivateStringreaderId;privateStringname;privateStringspec;privatebooleansex;privateDateborn;privateintnum;privateintsnum;privatebytephoto;/省略上面属性的get和set方法7.4.1 查询已借图书查询已借图书判断完成后,如果输入了正确的借书证号,就会分页查询,先来看看在LendDao中的查询方法。当在Action
14、中调用这个查询方法后,就会得到对应借书证号在lend表中的“pageSize”条记录,返回查询结果的List集。接下来就是Pager.java,即分页功能。其实,分页功能的处理有很多方法,不同的程序员写的方法可能不一样,但都能达到目的。本例的分页功能代码。Pager类中构造方法中要传入两个参数,一个是“pageNow”,另一个是“totalSize”,而“totalSize”是数据库中对应记录的总条数,故需要查询数据库,所以在创建Pager对象时:Pagerpage=newPager(pageNow,lendDao.selectLendSize(lend.getReaderId();7.4.1
15、 查询已借图书查询已借图书在LendDao中加入查询总记录的方法。在Action中调用方法查询完成后,把要保存的信息保存到request中,然后根据返回值在struts.xml中的配置返回到“lend.jsp”页面。此时由于request保存了该信息,就会在页面输出信息,输出代码就是要说的lend.jsp的第三部分:图书IDISBN书名出版社价格借书时间7.4.1 查询已借图书查询已借图书上面内容是显示存储在request中的list,但在做这部分功能时每次只查询了“pageSize”条记录,故在页面中应用了分页。下面看分页代码。当单击要显示的页面时,就把pageNow值传到了Action,A
16、ction就会根据pageNow的值查询要显示的list集,这样查询功能就基本完成了。在Action处理之前做了一些判断工作,如果输入的借书证号不合法或不存在就会直接返回并保存一些信息。在“lend.jsp”中也有相应的输出:7.4.2 “借书借书”功能功能前面讲解了“lend.jsp”根据借书证号查询已借图书的功能,“lend.jsp”中还有最后一个功能就是借书,首先看看其实现代码。读者可以发现,借书的输入框中也进行了判断,如果“readerId”没有值就让输入框不可编辑,这是因为如果没有“readerId”就不知道谁要借书了,这个很容易理解。输入了“借书证号”(即readerId),查询该
17、学生已借图书后,“readerId”就被保存到了request中,这时该部分就变成可操作了,输入要借书籍的“ISBN”及“图书ID”,单击“借书”按钮,提交到“lendBook.action”,该请求在struts.xml中配置为:/lend.jsp7.4.2 “借书借书”功能功能从“method=lendBook”可以看出,处理该功能的是LendAction中的lendBook方法,下面看该方法的实现。因为是在同一页面显示,故当借书时还要显示前面查询的已借图书,所以获取已借图书信息的代码和前面一样,不再多说。本功能在判断是否有用户输入的“ISBN”时应用了BookDao的“selectBoo
18、k”方法。7.4.2 “借书借书”功能功能图书模型Book.java代码为:packageorg.model;publicclassBookprivateStringISBN;privateStringbookName;privateStringauthor;privateStringpublisher;privatefloatprice;privateintcnum;privateintsnum;privateStringsummary;privatebytephoto;/省略上面属性的get和set方法7.4.2 “借书借书”功能功能调用该方法,如果返回的是null,就表示输入的“ISBN
19、”不存在,也就表示不存在该种图书。同样,在判断图书ID时,因为同一本书不能被同时借两次或多次,故在已经借的书中不能包含刚刚输入的图书ID,判断方法为LendDao中的“selectByBookId”方法,代码实现。如果返回“lend”,表示已经存在,将返回错误信息。通过判断都合法后,将应用LendDao中的“addLend”方法对其进行插入操作。由于该“ISBN”的图书被借出去一本,故该图书的库存量应该减少一本,所以在插入一条lend记录的同时要修改book的库存量:Bookbook=bookDao.selectBook(lend.getISBN();/取得该ISBN的图书对象book.set
20、Snum(book.getSnum()-1);/设置库存量-1bookDao.updateBook(book);7.4.2 “借书借书”功能功能在BookDao中的updateBook方法。同时,学生的借书量应该多出一本,故有这样的代码:StudentDaostudentDao=newStudentDao();Studentstu=studentDao.selectByReaderId(lend.getReaderId();stu.setNum(stu.getNum()+1);/设置学生的借书量+1studentDao.updateStudent(stu);7.4.2 “借书借书”功能功能所以
21、,在StudentDao中要编写修改学生信息的方法:publicvoidupdateStudent(Studentstu)tryconn=DBConn.getConn();PreparedStatementpstmt=conn.prepareStatement(updatestudentsetnum=?wherereaderId=?);pstmt.setInt(1,stu.getNum();pstmt.setString(2,stu.getReaderId();pstmt.executeUpdate();catch(Exceptione)e.printStackTrace();finallyD
22、BConn.CloseConn();7.5 实现实现“图书管理图书管理”功能功能单击“图书管理”,跳转到“bookmanage.jsp”,出现如图7.12所示的页面。图7.12 图书管理页面7.5.1 “图书追加图书追加”功能功能在实现该功能之前,先来看看“bookmanage.jsp”的实现。当填写完要添加的图书信息后,显示界面如图7.13所示。图7.13 图书添加界面7.5.1 “图书追加图书追加”功能功能可以发现,“图书追加”提交按钮代码:由于4个按钮均提交到“book.action”,故该提交代码中定义了“method=addBook”,表示提交后由Action类中的“addBook”
23、方法来处理,struts.xml中关于action的配置为:/bookmanage.jsp/bookmanage.jsp*addBook,updateBook7.5.1 “图书追加图书追加”功能功能通过该配置文件,系统会应用BookAction来处理请求,并根据提交的方法名来决定用哪个方法进行处理。Book的模型在借书部分已经给出,这里不再列举。本例中把照片传入数据库中用二进制流保存,而在页面中,由于用到文件上传,故“form”中要加入属性“enctype=multipart/form-data”,文件部分代码为:命名为“photo”,故在Action中有:privateFilephoto;7
24、.5.1 “图书追加图书追加”功能功能接收传过来的值,后面“onchange”表示当选择好图片的路径时,把:imgid=imagesrc=getImage.action?book.ISBN=width=100height=120中“src”值设置为选中的图片的路径。这样,当我们选择了图片时,就会在“img”的地方显示该图片。if(this.getPhoto()!=null)FileInputStreamfis=newFileInputStream(this.getPhoto();bytebuffer=newbytefis.available();fis.read(buffer);b.setPh
25、oto(buffer);7.5.1 “图书追加图书追加”功能功能这段代码是处理传入的文件,把文件转化为字节数组,完成后调用BookDao的“addBook”方法进行插入操作。该方法的代码。因为当添加记录时,需要对数据进行验证,本部分采用验证框架来处理,验证框架文件“BookAction-validation.xml”配置。struts.xml中的action配置为:/bookmanage.jsp/bookmanage.jsp*addBook,updateBook7.5.1 “图书追加图书追加”功能功能黑体部分是配置该action应用的拦截器,我们知道,action默认使用的拦截器是“defau
26、ltStack”,本例为action配置该拦截器,但加入了两个参数:*表示对所有方法都不验证,而addBook,updateBook表示验证“addBook”、“updateBook”两个方法,通过这样的设置,系统就会只验证“addBook”、“updateBook”两个方法。7.5.2 “图书删除图书删除”功能功能图书删除功能非常简单,输入“ISBN”后,单击“删除”按钮,就会根据BookAction中的“deleteBook”方法删除图书信息。“deleteBook”方法实现为:publicStringdeleteBook()throwsExceptionif(newLendDao().s
27、electByBookISBN(book.getISBN()!=null)this.setMessage(该图书已经被借出,不能删除);returnSUCCESS;Bookbo=bookDao.selectBook(book.getISBN();if(bo=null)/首先判断是否存在该图书this.setMessage(要删除的图书不存在!);returnSUCCESS;elseif(newLendDao().selectByBookISBN(book.getISBN()!=null)this.setMessage(该图书已经被借出,故不能删除图书信息!);returnSUCCESS;boo
28、kDao.deleteBook(book.getISBN();this.setMessage(删除成功!);returnSUCCESS;7.5.2 “图书删除图书删除”功能功能该功能用了三个方法,分别是BookDao中的“selectBook”、“deleteBook”及LendDao中的“selectByBookISBN”。“selectBook”方法前面已经给出,“deleteBook”方法实现为:publicbooleandeleteBook(StringISBN)tryconn=DBConn.getConn();PreparedStatementpstmt=conn.prepareSt
29、atement(deletefrombookwhereISBN=?);pstmt.setString(1,ISBN);pstmt.execute();returntrue;catch(Exceptione)e.printStackTrace();returnfalse;finallyDBConn.CloseConn();实现方法非常简单,这里就不多做解释了。LendDao中的“selectByBookISBN”方法实现。7.5.3 “图书查询图书查询”功能功能输入“ISBN”后,单击“图书查询”按钮,就会根据BookAction中的“selectBook”方法处理,查询该图书信息。“selec
30、tBook”方法实现为:publicStringselectBook()throwsExceptionBookonebook=bookDao.selectBook(book.getISBN();if(onebook=null)this.setMessage(不存在该图书!);returnSUCCESS;Maprequest=(Map)ActionContext.getContext().get(request);request.put(onebook,onebook);returnSUCCESS;7.5.3 “图书查询图书查询”功能功能图书查询在Dao中的实现方法,在“借书”功能中已经列出,方
31、法也非常简单,这里就不再过多介绍。需要指出的是,当查询图书时需要对图书的封面图片进行处理,在页面的显示代码为:imgid=imagesrc=getImage.action?book.ISBN=width=100height=120可以看出,它单独提交到一个action,该action在struts.xml中的配置为:*addBook,updateBook7.5.3 “图书查询图书查询”功能功能BookAction中的方法实现为:publicStringgetImage()throwsExceptionHttpServletResponseresponse=ServletActionContex
32、t.getResponse();StringISBN=book.getISBN();Bookb=bookDao.selectBook(ISBN);bytephoto=b.getPhoto();response.setContentType(image/jpeg);ServletOutputStreamos=response.getOutputStream();if(photo!=null&photo.length!=0)for(inti=0;iphoto.length;i+)os.write(photoi);os.flush();returnNONE;7.5.3 “图书查询图书查询”功能功能例
33、如,输入“ISBN”为刚刚添加进去的“123459”时,单击“图书查询”,出现如图7.14所示的页面。图7.14图书查询页面7.5.4 “图书修改图书修改”功能功能图书修改功能一般是根据“ISBN”查询出来后进行修改的。例如,要对“ISBN”为“123459”的图书的“内容提要”内容进行修改,只需查询出此书,然后修改该部分内容,并上传照片,单击“图书修改”按钮即可,如图7.15所示。图7.15 修改图书页面7.5.4 “图书修改图书修改”功能功能单击“图书修改”按钮,就会在页面的下方显示“修改成功”字样,再次输入“ISBN”为“123459”查询,就会出现修改过的信息。修改图书应用的BookAction中的方法。