JSP/Servlet开发——第六章 JSP开发业务应用
1、 大容量的数据显示的缺点:
●当数据量较多时,用户需要拖动页面才能浏览更多信息;
●数据定位不便;
2、分页显示:
●既能显示多条数据,又不需要拖动页面,是数据更加清晰直观,页面不再冗长,也不受数据量的限制; |
||||||
●实现分页的方式下面两种: ★一、例如,将所有查询结果以集合等形式保存在内存中,翻页时从中取出一页所需的数据显示: ◆这种方法有两个主要的缺点: 1、用户看到的可能是过期数据; 2、如果数据量非常大,查询一次数据集会耗费很长时间,并且存储的数据也会占用大量内存开销。 ★二、每次翻页时只从数据库中检索出本页需要的数据。 ◆虽然每次翻页都查询数据库,但查询出的记录数相对较少,总体开销不大,再配以连接池技术以及其他查询优化。可以达到比高的效率。 |
||||||
●实现分页显示的步骤: 1、确定每页显示的数据数量; ◆根据实际的页面设计,确定在数据列表中每次显示多少条记录 . 即每次从数据库中需要查询多少条记录用于页面显示,通常这个数量可以在开发时定义好,也可以由用户来选择; 2、计算分页显示所需的总页数; ◆既然要进行分页显示,还需清楚按照每页显示的记录数量总共会产生多少页数据,在页面中示的记录数量是已知的,而数据库中符合展示条件的记录总数是未知的; 3、编写SQL查询语句,实现数据查询; 4、在JSP页面中进行分页显示设置; ■详解: ●得到总页数的步骤: ★通过查询获取符合展示条件的总记录数,可以借助count()聚合函数实现; ▲select count(1) from 表名 效率高于 select count(*) from 表名
★有了需要展示的记录总数后,就可以根据每页显示的记录数计算共需要划分为多少页。基于方便代码管理的考虑,将有关分页的数据封装到一个Page 类中 ,其中包括每页显示的数据量、数据的总数量、显示的总页数、当前页码、每页显示的数据集合。
●编写SQL语句:不同数据库厂商实现分页的SQL语句之间存在差异,因此在实际应用中根据数据库的不同,需要修改相应的SQL语句; ◆编写 SOL 语实现数据分页显示的关键是如何编写 SQL 查询语句,MySQL数据库中,可以使用 LIMIT 子句现分页需求; eg:每页显示三条记录,若要显示第一页的记录,则SQL语句: SELECT `nid`, `ntitle`, `ncreateDate` FROM `news` LIMIT 0, 3 SQL语句分析: ▲在这段 SQL 语句中 , LIMIT 子句的两个参数分别代表起始行偏移量和最大返回行数。最大返回数相当于每页显示的记录数,是一个固定值。而每页数据起始行的偏移量是动态的; ▲应该如何确定:假设每页显示三条数据,取第一页的数据时,不需要偏移。即起始行偏移量是 0,第二页时则需越过第一页数据,即偏移 3 条记录后再开始提取;而第三页则需越过前两页数据,即偏移 2*3记录; ▲可以从中总结出一个规律: 起始行偏移量=(当前页页码-1) *每页显示的记录数; 所以上面的代码可以该为: SELECT `nid`, `ntitle`, `ncreateDate` FROM `news` LIMIT (当前页页码-1) *每页显示的记录数,每页显示的记录数 eg:下面通过访问数据库来获得每页显示的新闻集合,代码修改如下:
●在上面的代码中,将查询结果进行了降序排列,下面,添加测试分页的功能,
|
3、用 Commons-FileUpload 组件实现文件上传:
●Commons是Apache 开放源代码组织的一个 Java 子项目,该项目主要涉及一些开发中常用的模块,如文件上传、命令行处理、数据库连接等;FileUpload就是其中的一个用于处理 HTTP 文件传的子项目 |
||||||||||||||||||||||||||||||
●组件具有以下几个特点: ★使用简单:Commons-FileUpload 组件可以方便地嵌入 JSP 文件中 , 在 JSP文件中仅编写堆代码即可完成文件的上传功能,十分方便; ★能够全程控制上传内容:使用 Commons-FileUpload组件提供的对象及操作方法,可以获全部上传文件的信息,包括文件名称、类型、大小等,方便操作; ★能够对上传文件的大小,类型进行控制:为了避免在上传过程中出现异常数据,在Commons-FileUpload组建中,专门提供了相应的方法用于对上传文件进行控制; |
||||||||||||||||||||||||||||||
●获取Commons-FileUpload组建的步骤: (1) 登录网站http://commons.apache.org/fileupload下裁 Commons-FileUpload 组件,即commons-fileupload-1.2.2-bin.zip, 将下载的文件解压,得到commons-fileupload-1.2.2文件夹。其中,commons-fileupload-1.2.2/lib/ commons-fileupload-1.2.2.jar即为Commons-FileUpload组件类库。commons-fileupload-1.2.2\site\apidocs为Commons-FileUpload组件的API文档,可以访问index.html查阅相关的类和接口; ( 2 ) 登录网站 http://commons.apache.org/io下载Commons-IO组件,即 commons-io-2.4-bin.zip。该组件用干处理文件上传所依赖的 I/O操作。将下载的commons-io-2.4-bin.zip文件解压,得到commons-io-2.4文件夹。其中commons-io-2.4.jar文件即为Commons-IO组件类库,commons-io-2.4\docs为Commons-IO组件的API文档,可以访问index.html相关的类和接口; |
||||||||||||||||||||||||||||||
●设置表单的enctype属性 ★文件上传时,需要在表单属性中添加 enctype 属性,该属性用于设置表单提交数据的编码方式,由于文件传至服务器时语言一般文本类型的编码不同,需要使用 multipart/form-data 的编码方式。 ◆设置该属性的方法:<form enctype="multipart/form-data" method="post"> //上传文件时form标签的method属性取值必须为post,不能为get; ▲表单的enctype的属性的三个值: ☉application/x-www-form- urlencoded:默认值,该属性主要用于处理少量文本数据的传递,在向服务器发送大量的文件包含非ASCII字符的文本或 二进制数据时效率很低; ☉multipart/form-data:上传二进制数据,只有使用了multipart/form-data才能完整地递文件数据,进行上传操作; ☉text/plain : 主要用干向服务器传递大量文本数椐,比较适用干电子邮件的应用; |
||||||||||||||||||||||||||||||
●使用File 控件选择文件: eg:在表单中添加 File 控代码:、 <body> <form action="doupload.jsp" enctype="multipart/form-data" method="post"> <p>姓名:<input type="text" name="user"></p> <p>选择图片:<input type="file" name="nfile"></p> <p><input type="submit" value="提交"></p> </form> </body> |
||||||||||||||||||||||||||||||
●Commons-FileUpload组件的API: ◆在使用Commons-FileUpload组件之前:环境准备:在项目中引入commons-fileupload-1.2.2.jar和commons-io-2.4.jar文件,添加完成jar之后,在JSP文件中还需要将Commons-FileUpload组件所使用的类库导入JSP文件中,代码:<%@ page import="org.apache.commons.fileupload.*"%> ◆ServletFileUpload类:用于实现文件上传操作; ☆ServletFileUpload类的常用方法:
◆FileItem接口:用于封装单个表单字段元素的数据,一个字段表单元素对应一个FileItem实例,在应用程序中使用的是其实现类DiskFileltem; ☆FileItem接口的常用方法:
◆FileItemFactory接口与实现类:创建ServletFileUpload实例需要依赖FileItemFactory工厂接口,DiskFileItemFactory是FileItemFactory接口的实现类; ☆DiskFileItemFactory类的常用方法:
|
||||||||||||||||||||||||||||||
●Commons-FileUpload组件实现文件上传的功能: <%@ page language="java" pageEncoding="UTF-8"%> <%@page import="java.io.*,java.util.*"%> <%@page import="org.apache.commons.fileupload.*"%> <%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %> <%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>上传处理页面</title> </head> <body> <% request.setCharacterEncoding("utf-8"); String uploadFileName = ""; //上传的文件名 String fieldName = ""; //表单字段元素的name属性值 //请求信息中的内容是否是multipart类型 boolean isMultipart = ServletFileUpload.isMultipartContent(request); //上传文件的存储路径(服务器文件系统上的绝对文件路径) String uploadFilePath = request.getSession().getServletContext().getRealPath("upload/" ); if (isMultipart) { FileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); try { //解析form表单中所有文件 List<FileItem> items = upload.parseRequest(request); Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { //依次处理每个文件 FileItem item = (FileItem) iter.next(); if (item.isFormField()){ //普通表单字段 fieldName = item.getFieldName(); //表单字段的name属性值 if (fieldName.equals("user")){ //输出表单字段的值 out.print(item.getString("UTF-8")+"上传了文件。<br/>"); } }else{ //文件表单字段 String fileName = item.getName(); if (fileName != null && !fileName.equals("")) { File fullFile = new File(item.getName()); File saveFile = new File(uploadFilePath, fullFile.getName()); item.write(saveFile); uploadFileName = fullFile.getName(); out.print("上传成功后的文件名是:"+uploadFileName); } } } } catch (Exception e) { e.printStackTrace(); } } %> </body> </html> 分析:上面的的代码完成了一个文件上传的功能,对于其中的关键步骤总结如下: ◆在JSP 文件中使用 page 指令导入Commons-FileUpload组件所需的类; ◆判断请求信息中的内容是否是 multipart 类型 , 如果是则进行处理; ◆通过FileltemFactory 厂对象实例化 ServletFileUpload对象; ◆通过ServletFileUpload对象的parseRequest()将表单中字段解析成Fileltem 对象的集合; ◆通过迭代依次处理每个Filellem对象,如果是普通字段,通过 getString()方法得到相应表单字符的值,该值与表单字段的中的“name”属性对应,如果是文件字段,则通过 File 的构造方法构建一个指定路径名和文件名的文件,并通过Fileltem 对象的 write()方法将上传文件的内容保存到文件中; |
||||||||||||||||||||||||||||||
编写上传文件处理页的实现步骤 1. 创建FileItemFactory对象 2. 创建ServletFileUpload对象 : 通过构造方法:ServletFileUpload( FileItemFactory ) 3. 解析form表单提交的所有表单元素数据 ●如果是普通表单元素: 获取该元素的名和值使用
|
4、 用 Commons-FileUpload组件控制文件上传:
●控制文件上传的类型和大小: eg: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@page import="java.io.*,java.util.*,org.apache.commons.fileupload.FileItem"%> <%@page import="org.apache.commons.fileupload.*"%> <%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %> <%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>上传处理页面</title> </head> <body> <% request.setCharacterEncoding("utf-8"); String uploadFileName = ""; //上传的文件名 String fieldName = ""; //表单字段元素的name属性值 //请求信息中的内容是否是multipart类型 boolean isMultipart = ServletFileUpload.isMultipartContent(request); //上传文件的存储路径(服务器文件系统上的绝对文件路径) String uploadFilePath = request.getSession().getServletContext().getRealPath("upload/" ); //创建临时文件目录路径 File tempPatchFile=new File("d:\\temp\\buffer\\"); if(!tempPatchFile.exists()) //判断文件或目录是否存在 tempPatchFile.mkdirs(); //创建指定的目录,包括所有必需但不存在的父目录 if (isMultipart) { DiskFileItemFactory factory=new DiskFileItemFactory(); //设置缓冲区大小4kb factory.setSizeThreshold(4096); //设置上传文件用到临时文件存放路径 factory.setRepository(tempPatchFile); ServletFileUpload upload = new ServletFileUpload(factory); //设置单个文件的最大限制 upload.setSizeMax(1024*30); try { //解析form表单中所有文件 List<FileItem> items = upload.parseRequest(request); Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { //依次处理每个文件 FileItem item = (FileItem) iter.next(); if (!item.isFormField()){ //文件表单字段 String fileName = item.getName(); //通过Arrays类的asList()方法创建固定长度的集合 List<String> filType=Arrays.asList("gif","bmp","jpg"); String ext=fileName.substring(fileName.lastIndexOf(".")+1); if(!filType.contains(ext)) //判断文件类型是否在允许范围内 out.print("上传失败,文件类型只能是gif、bmp、jpg"); else{ if (fileName != null && !fileName.equals("")) { File fullFile = new File(item.getName()); File saveFile = new File(uploadFilePath, fullFile.getName()); item.write(saveFile); uploadFileName = fullFile.getName(); out.print("上传成功后的文件名是:"+uploadFileName+",文件大小是:"+item.getSize()+"bytes!"); } } } } }catch(FileUploadBase.SizeLimitExceededException ex){ out.print("上传失败,文件太大,单个文件的最大限制是:"+upload.getSizeMax()+"bytes!"); }catch (Exception e) { e.printStackTrace(); } } %> </body> </html> |
分析:对控制文件类型进行分析: ◆用到了 Arnnys 类,此类包含用于操作数组 (如排序和搜索 ) 的各种方法 , 通过Arrays类的asList()方法创建固定长度的集合,也就是得到允许文件类型的集合,然后通过集合的 contains()方法匹配上传文件的扩展名来判断文件类型是否在允许范围内。如图:
|
分析:对控制文件大小进行分析: ◆如果上传的文件大小超出了设置的要求,系统会返回错误信息;如图:
◆在上面的示例代码中:创建临时文件目录路径,通过 DiskFileltemFactory 对象的 setSizeThreshold ( ) 方法设置缓冲区大小,当上传文件大小超过缓冲区大小。则临时存储在通过 DiskFileltemFactary 对象的setReposilory ( ) 方法设置的临时文件目录路径。同时通过 ServletFileUpload 对象的 setSizeMax()限制了一个完整请求的最大字节数,如果超出设置的字节数,则会抛出一个 FileUploadBase.SizeLimitExceededException 类型的异常,并通过异常处理提示错误信息; |
●FileUploadBase.SizeLimitExceededException是一个静态内部类,内部类是指定义在个类内部的类。内部类作为外部类的一个成员,并且依附于外部类而存在,这里FileUploadBase 就是外部类,而 SizeLimitExceededException 就是定义在FileUploadBase内部的由static修饰的类; |