Excel文件的导入导出实战(2)--完成学生信息导出为Excel文件模块

接着来

首先我们看看配置文件,web.xml:

这个没什么特别的,自动生成


然后是Struts2.xml:


其他几个action先不用管,就关注MainAction...

当我们输入http://localhost:8080/main的时候,action拦截到请求,会把我们带到layout.jsp页面,也就是我们的主页面

主页面是用Jquery.easyUI写的,非常简单干净:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>web 文件导入导出Demo</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<link rel="stylesheet" type="text/css" href="css/common.css" />
	<script type="text/javascript" src="../js/jquery-easyui-1.2.6/jquery-1.7.2.min.js"></script>
	<link rel="stylesheet" type="text/css" href="../js/jquery-easyui-1.2.6/themes/default/easyui.css" />
	<link rel="stylesheet" type="text/css" href="../js/jquery-easyui-1.2.6/themes/icon.css" />
	<script type="text/javascript" src="../js/jquery-easyui-1.2.6/jquery.easyui.min.js"></script>
	<script type="text/javascript" src="../js/jquery-easyui-1.2.6/locale/easyui-lang-zh_CN.js"></script>

	<script type="text/javascript">
	
			$(function(){
				$('a[title]').click(function(){
						var src = $(this).attr('title');
						var title = $(this).html();
						//当前标签页是否存在,存在就选择,不存在就新加上去 from JqueryUI
						if($('#tt').tabs('exists' ,title)){
							$('#tt').tabs('select',title);
						} else {
							$('#tt').tabs('add',{   
							    title:title,   
							    content:'<iframe frameborder=0 style=width:100%;height:100% src='+ src +' ></iframe>',   
							    closable:true  
							});  
						}
				});
			});
	
	</script>
  </head>
  
  <body>
    <div id="cc" class="easyui-layout" fit=true style="width:100%;height:100%;">  
		<div region="west"  split="true" title="菜单" style="width:200px;">
			<div id="aa" class="easyui-accordion" fit=true >
				<div title="Excel导入导出"  selected="true"  style="overflow:auto;padding:10px;">
					<a title="jsp/importList.jsp" >数据导入</a> <br/>
					<a title="jsp/studentList.jsp" >学生信息</a>
				</div>
			</div>
		</div>
		<div region="center"  title="主界面" style="padding:5px;">
			<div id="tt" class="easyui-tabs" fit=true style="width:500px;height:250px;">
			</div>
		</div>
	</div>
  </body>
</html>

好了,到这儿我们的基本框架和主页面就搭建起来了。运行看看:


非常简洁的界面

接下来我们看看学生信息一项。当点击学生信息的时候,右边的效果是这样的:

要想达到这个效果,我们需要做些事情。

1.用Mysql或者别的都行,只要你喜欢,建立一个student的库,设置上图对应的6个字段

2.往你建的表中插入几条数据

3.建立一个Model类,关联你表的字段,提供get/set方法

4.建立StudentService类,实现对数据库的CRUD

5.建立StudentAction类,并在struts2.xml中配置

6.界面布局和分页用的是easyUI的API,简单易懂

好的,我们1个1个来,首先数据库建表部分就省略了。这个板块需要注意的就是可能从Mysql上查询出的数据有中文乱码;怎么解决自行百度。

插入测试数据省略....

model类省略....

struts的配置我在上边已经给大家展示了:

需要注意的是有一点:



这里用的name="student-*",struts2在我们平时用的时候,大家习惯直接用student?getList.action。这种方式,但是官方是不推荐这样的,最好还是用上图这种

studentList.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'importList.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<link rel="stylesheet" type="text/css" href="css/common.css" />
	<script type="text/javascript" src="../js/jquery-easyui-1.2.6/jquery-1.7.2.min.js"></script>
	<link rel="stylesheet" type="text/css" href="../js/jquery-easyui-1.2.6/themes/default/easyui.css" />
	<link rel="stylesheet" type="text/css" href="../js/jquery-easyui-1.2.6/themes/icon.css" />
	<script type="text/javascript" src="../js/jquery-easyui-1.2.6/jquery.easyui.min.js"></script>
	<script type="text/javascript" src="../js/jquery-easyui-1.2.6/locale/easyui-lang-zh_CN.js"></script>
	<script type="text/javascript" src="../js/commons.js"></script>
	
	<script type="text/javascript">
	
			$(function(){
					
				/**
				 *	初始化数据表格  
				 */
				$('#t_student').datagrid({
						idField:'id' ,		
						title:'数据列表' ,
						fit:true , //自动补全
						height:450 ,
						url:'student-list' , //访问地址
						fitColumns:true ,
						striped: true ,					//隔行变色特性 
						loadMsg: '数据正在加载,请耐心的等待...' ,
						rownumbers:true ,
						frozenColumns:[[				//冻结列特性 ,不要与fitColumns 特性一起使用 
								{
									field:'ck' ,
									width:50 ,
									checkbox: true
								}
							]],
						columns:[[ //每个列具体内容
							{
								field:'sid' ,
								title:'Student id' ,
								hidden:true
							},{
								field:'stunum' ,
								title:'编号' ,
								width:100 ,
								sortable : true 
							},{
								field:'stuname' ,
								title:'姓名' ,
								width:100 ,
								sortable : true 
							},{
								field:'stuage' , 
								title:'年龄' ,
								width:100 
							},{
								field:'stusex' , 
								title:'性别' ,
								width:100
							},{
								field:'stubirthday' , 
								title:'出生日期' ,
								width:100
							},{
								field:'stuhobby' , 
								title:'爱好' ,
								width:100
							}
						]] ,
						pagination: true , //显示分页
						pageSize: 10 , //分页大小
						pageList:[5,10,15,20,50], //每页个数
						toolbar:[  //工具条
							{
								text:'导出excel',
								iconCls:'icon-save',
								handler:function(){  //回调函数
									//获取后台传递参数 className  methodName
									var className = $('#t_student').datagrid('getData').className;
									var methodName = $('#t_student').datagrid('getData').methodName;
									//alert(JSON.stringify($('#t_student').datagrid('getData')))
									//获取表头信息
									var header = $('#t_student').datagrid('options').columns[0];
									//alert(JSON.stringify($('#t_student').datagrid('options')));
									var fields = "";
									var titles = "";
									for(var i = 0;i<header.length;i++){
										var field = header[i].field;
										var title = header[i].title;
										var hiddenFlag = header[i].hidden;//sid默认为true 隐藏
										if(!hiddenFlag){
											var dh = i == (header.length -1) ? "" :",";
											fields = fields + field + dh;
											titles = titles + title + dh;
										}
									}
									//向后台发送请求  
									var form = $("<form>");//定义一个form表单
									form.attr('style','display:none');
									form.attr('target','');
									form.attr('method','post');
									form.attr('action','student-export');
									//添加input
									var input1 = $("<input>");
									input1.attr('type','hidden');
									input1.attr('name','fields');
									input1.attr('value',fields);
									
									var input2 = $("<input>");
									input2.attr('type','hidden');
									input2.attr('name','titles');
									input2.attr('value',titles);
									
									var input3 = $("<input>");
									input3.attr('type','hidden');
									input3.attr('name','className');
									input3.attr('value',className);
									
									var input4 = $("<input>");
									input4.attr('type','hidden');
									input4.attr('name','methodName');
									input4.attr('value',methodName);
									
									//将表单放到body中
									$('body').append(form);
									form.append(input1);
									form.append(input2);
									form.append(input3);
									form.append(input4);
									form.submit();//提交表单
									
								}
							}
						]
						
				});
		});
			
	</script>
  </head>
  
  <body>
		<div id="lay" class="easyui-layout" style="width: 100%;height:100%" >
				<div region="center" >
					<table id="t_student"></table>
				</div>
		</div>
  </body>
</html>


service类:
package com.huangteng.demo.service;

import com.huangteng.demo.model.Student;
import com.huangteng.demo.utils.DB;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class StudentService {
    /**
     * 分页查询学生信息
     * @param currentPage
     * @param pageSize
     * @param sort
     * @param order
     * @return list
     */
    public List<Student> list(int currentPage, int pageSize,String sort,String order){
        Connection conn = DB.creatConn();
        String sql = "select * from t_student where 1=1 ";
        if(StringUtils.isNotBlank(sort)){
            sql += "order by " + sort ;
        }
        if(StringUtils.isNotBlank(order)){
            sql += " " + order ;
        }
        if(currentPage>0 && pageSize >0){
            sql += " limit " + (currentPage-1)*pageSize +" , "  + pageSize ;
        }

        PreparedStatement ps = DB.prepare(conn,sql);
        List<Student> list1 = new ArrayList<Student>();
        try {
            ResultSet rs = ps.executeQuery();
            Student s = null;
            while (rs.next()){
                s = new Student();
                s.setSid(rs.getInt("sid"));
                s.setStunum(rs.getString("stunum"));
                s.setStuname(rs.getString("stuname"));
                s.setStuage(rs.getString("stuage"));
                s.setStusex(rs.getString("stusex"));
                s.setStubirthday(rs.getString("stubirthday"));
                s.setStuhobby(rs.getString("stuhobby"));

                list1.add(s);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        DB.close(conn);
        DB.close(ps);
        return list1;
    }

    //获取总数
    public int getTotal(){
        Connection conn = DB.creatConn();
        int total = 0;
        String sql = "select count(*) from t_student";
        PreparedStatement ps = DB.prepare(conn,sql);
        try {
            ResultSet rs = ps.executeQuery();
            while(rs.next()){
                total = rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        DB.close(ps);
        DB.close(conn);
        return total;
    }
}

这里的DB是我写的一个工具类,就是获取Connection,然后用prepareStatement执行sql语句,最后提供关闭连接和流的close方法。

这里希望大家也自己动手写写工具类,并保存,以后在项目中直接引用就行,就不必再写了。

再看看Action:

package com.huangteng.demo.action;

import com.alibaba.fastjson.JSON;
import com.huangteng.demo.model.Student;
import com.huangteng.demo.service.StudentService;
import com.huangteng.demo.utils.ExportUtils;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.struts2.ServletActionContext;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Created by ht on 2016/8/7.
 */
public class StudentAction  extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private StudentService studentService = new StudentService();
    //分页
    private int page;
    private int rows;
    private String sort;
    private String order;

    private String className;
    private String methodName;

    private String fields;
    private String titles;

    public String getTitles() {
        return titles;
    }

    public void setTitles(String titles) {
        this.titles = titles;
    }

    public String getFields() {
        return fields;
    }

    public void setFields(String fields) {
        this.fields = fields;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getRows() {
        return rows;
    }

    public void setRows(int rows) {
        this.rows = rows;
    }

    public String getSort() {
        return sort;
    }

    public void setSort(String sort) {
        this.sort = sort;
    }

    public void list(){
        //System.out.print("进入list方法中...");
        HttpServletResponse response = ServletActionContext.getResponse();
        response.setContentType("text/html;charset=utf-8");
        int total = studentService.getTotal();
        List<Student> slist = getStudents();
        //System.out.println("JSON数组:"+ JSON.toJSONString(slist));
        String json = "{\"total\":"+total+" , " +
                "\"rows\":"+JSON.toJSONString(slist)+ "," +
                "\"className\":\"" + StudentAction.class.getName() + "\"," +
                "\"methodName\":\"getStudents\"}";
        //System.out.println(json);
        try {
            response.getWriter().write(json);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public List<Student> getStudents(){
        //System.out.print("进入getStudents....");
        List<Student> slist = studentService.list(page,rows,sort,order);
        return slist;
    }

    public void export(){
        HttpServletResponse response = ServletActionContext.getResponse();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=export.xls");
        //创建Excel
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("sheet0");
        /*
           导出学生信息时需要再次从后台查询数据,利用反射实现
         */
        try {
            Class clazz = Class.forName(className); //加载类
            Object obj = clazz.newInstance();       //创建对象
            Method m = clazz.getDeclaredMethod(methodName); //获取方法
            List list = (List) m.invoke(obj);
            ExportUtils.outputHeaders(titles.split(","),sheet);//导出header
            ExportUtils.outputColumns(fields.split(","),list,sheet,1);//导出内容
            //获取输出流,写入数据
            ServletOutputStream out = response.getOutputStream();
            wb.write(out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这里细细谈谈我的总结:

在这个action中,业务逻辑很简单,就是调用service层的方法从数据库查询学生的信息,返回一个list<Student>的集合。然后通过response把数据反馈给前台,当然这个数据要

做一下处理,把list转成JSON数组,我本来考虑的是用JSONArray.fromObject();但是没成功而且效率低下,后来考虑用阿里巴巴温少开发的fastjson.这是一个开源项目,

通过序列化和反序列话实现,效率很高,而且轻量方便。这儿就不过多安利了,有兴趣的百度。

在struts2中后台获取前台传过来的数据有三种方法,我这里就是直接使用的,声明属性,提供get/set方法即可。

在studentAction中共有8个属性,前四个是实现分页的。 中间的两个是获取类名和方法名,然后用来实现反射,后两个是获取到每一列的字段名,然后用反射来获取值得。

Action中的ExportUtils是我封装的一个工具类,用于实现页面数据导出为Excel

ExportUtils:
package com.huangteng.demo.utils;

import org.apache.poi.hssf.record.chart.ObjectLinkRecord;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;

import java.lang.reflect.Method;
import java.util.List;

/**
 * Created by ht on 2016/8/8.
 * 导出为Excel文件的工具类
 */
public class ExportUtils {

    //导出header
    public static void outputHeaders(String[] headersInfo, HSSFSheet sheet){
        HSSFRow row = sheet.createRow(0);
        for(int i =0;i<headersInfo.length;i++){
            sheet.setColumnWidth(i,4000);
            row.createCell(i).setCellValue(headersInfo[i]);
        }
    }

    //导出主体内容
    public static void outputColumns(String[] headersInfo, List columnsInfo,HSSFSheet sheet,int rowIndex ){
        HSSFRow row ;
        int headerSize = headersInfo.length;
        int columnSize = columnsInfo.size();
        //循环导出数据
        for (int i = 0; i < columnsInfo.size(); i++) {
            row = sheet.createRow(rowIndex+i);
            Object obj = columnsInfo.get(i);
            //每一列
            for (int j = 0; j < headersInfo.length; j++) {
                Object value = getFieldValueByName(headersInfo[j],obj);
                row.createCell(j).setCellValue(value.toString());
            }
        }

    }

    /**
     * 利用反射,通过get/set方法来获取每一column对应的值
     * @param fieldName
     * @param obj
     * @return
     */
    private static Object getFieldValueByName(String fieldName, Object obj) {
        String firstLetter = fieldName.substring(0,1).toUpperCase();
        String getter = "get" +firstLetter + fieldName.substring(1);
        try {
            Method method = obj.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(obj, new Object[]{});
            return value;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("反射异常");
            return null;
        }
    }
}


当你完成这一步的时候,页面应该是这样了:

这时候你点及左上的导出Excel:

它应该是这样的:
1.下载成功


2.打开excel文件


ok

这一部分就结束了。后续是如何解析一个XML文件生成固定格式的Excel模板,可以下载上传。

//打游戏去了.....

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值