SSM整合补充pageHelper,POI与事务

1 ssm整合PageHelper

1.1 导入jar包

jsqlparser-3.1.jar
pagehelper-5.1.10.jar

1.2 配置pagehelper插件

  • 方式1:如果有mybatis的配置文件:在mybatis的配置文件中添加
<!-- 导入pagehelper的插件 -->
 <plugins>
           <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
 </plugins>
  • 方式2:如果没有mybatis的配置文件:在spring的核心配置文件中添加
<!--3.创建sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <!--配置mybatis 插件-->
    <property name="plugins">
        <set>
            <!--配置pageHelper 分页插件-->
            <bean class="com.github.pagehelper.PageInterceptor">
                <property name="properties">
                    <props>
                        <!--方言:-->
                        <prop key="helperDialect">mysql</prop>
                    </props>
                </property>
            </bean>
        </set>
    </property>
</bean>

1.3 创建dao

     <select id="getAll" resultType="com.zhiyou100.entity.Student">
          select * from student
      </select>
       <select id="getAllByMinScore" resultType="com.zhiyou100.entity.Student" parameterType="float">
          select * from student where score > #{score}
      </select>

      <!--  int count();-->
      <select id="count" resultType="int">
          select count(*) from student
      </select>
      <select id="countByMinScore" resultType="int"  parameterType="float">
          select count(*) from student where score > #{score}
      </select>

1.4 创建service

	public PageInfo<Student> getAllFenYe(int pageNumber) {
		int pageSize=5;
		PageHelper.startPage(pageNumber, pageSize);
		
		PageInfo<Student> info=new PageInfo<>(studentMapper.getAll());
        //通过构造方法传递一个list  其他属性都有值
        //不能通过set方法传递:否则只有当前属性有值
		//info.setList(studentMapper.getAll());
		//info.setTotal(studentMapper.count());//设置总记录数
		//info.setPages((int)Math.ceil(studentMapper.count()*1.0/pageSize));
		//info.setPageNum(pageNumber);
		return info;
	}
	public PageInfo<Student> getAllByMinScoreFenYe(int pageNumber,float score) {
		int pageSize=5;
		PageHelper.startPage(pageNumber, pageSize);
		PageInfo<Student> info=new PageInfo<>();
		info.setList(studentMapper.getAllByMinScore(score));
		info.setTotal(studentMapper.countByMinScore(score));//设置总记录数
		info.setPages((int)Math.ceil(studentMapper.countByMinScore(score)*1.0/pageSize));
		info.setPageNum(pageNumber);
		return info;
	}

1.5 test测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring_config.xml","classpath:springmvc_config.xml"})
public class TestStudentService {
	
	@Autowired//引入要测试的类
	private StudentService studentService;
	
	@Test//单元测试要求:类必须是public:方法声明必须是 public void xx();
	public void testGetAll(){
		System.out.println(studentService.getAllFenYe(2));
	}
	@Test//单元测试要求:类必须是public:方法声明必须是 public void xx();
	public void testGetAllByMinScore(){
		System.out.println(studentService.getAllByMinScoreFenYe(2, 20));
	}
}

1.6 action

@RequestMapping("/getAllFenYe.action")
public String getAllFenYeMethod(@RequestParam(value="pageNumber",required=false,defaultValue="1")int pageNumber,Model m){
    PageInfo<Student> pageInfo=studentService.getAllFenYe(pageNumber);
    m.addAttribute("pageInfo", pageInfo);
    return "student_manager02";
}

1.7 jsp:student_manager02.jsp

<script type="text/javascript" src="<c:url value='/js/jquery-1.6.4.min.js'/>"></script>
<h1>学生管理页面2:分页</h1>
<c:if test="${empty requestScope.pageInfo}">
    <jsp:forward page="/student/getAllFenYe.action?pageNumber=1"/>
</c:if>
<c:if test="${not empty requestScope.message}">
    提示信息是:${requestScope.message}  
</c:if>
<table>
    <tr>
        <th>顺序</th>
        <th>学号</th>
        <th>名字</th>
        <th>年龄</th>
        <th>党员</th>
        <th>生日</th>
        <th>分数</th>
        <th>真名</th>
    </tr>
    <c:forEach items="${requestScope.pageInfo.list}"  varStatus="vs" var="stu">
        <tr>
            <td>${vs.index+1}</td>
            <td>${stu.sid}</td>
            <td>${stu.sname}</td>
            <td>${stu.sage}</td>
            <td>
                <c:choose>
                    <c:when test="${stu.sdy}"> 是</c:when>
                    <c:otherwise>否</c:otherwise>
                </c:choose>
            </td>
            <td>
                <fmt:formatDate value="${stu.sbirthday}" pattern="yyyy年MM月dd日"/>
            </td>
            <td>${stu.score}</td>
            <td>${stu.realName}</td>
        </tr>
    </c:forEach>
</table>
requestScope.pageInfo.pages=${requestScope.pageInfo.pages}<br/>
<div id="div_fenye">
    <c:if test="${requestScope.pageInfo.pageNum != 1}">
        <a href="<c:url value='/student/getAllFenYe.action?pageNumber=${requestScope.pageInfo.pageNum-1}'/>">上一页</a>
    </c:if>
    <c:forEach begin="1" end="${requestScope.pageInfo.pages}" var="pn">
        <c:choose>
            <c:when test="${pn eq requestScope.pageInfo.pageNum}">
                [ ${pn} ]
            </c:when>
            <c:otherwise>
                <a href="<c:url value='/student/getAllFenYe.action?pageNumber=${pn}'/>"> ${pn} </a>
            </c:otherwise>
        </c:choose>
    </c:forEach>
    <c:if test="${requestScope.pageInfo.pageNum lt requestScope.pageInfo.pages}">
        <a href="<c:url value='/student/getAllFenYe.action?pageNumber=${requestScope.pageInfo.pageNum+1}'/>">下一页</a>
    </c:if>
</div>

1.8 效果

image-20211116151932413

2 poi

2.1 概念

Apache POI [1]  是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。

2.2 下载jar包

https://www.apache.org/dyn/closer.lua/poi/release/bin/poi-bin-4.0.0-20180907.tar.gz

image-20211116160319889

2.3 类解析

HSSF [1]  - 提供读写Microsoft Excel XLS格式档案的功能。

XSSF [1]  - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。

HWPF [1]  - 提供读写Microsoft Word DOC格式档案的功能。

HSLF [1]  - 提供读写Microsoft PowerPoint格式档案的功能。

HDGF [1]  - 提供读Microsoft Visio格式档案的功能。

HPBF [1]  - 提供读Microsoft Publisher格式档案的功能。

HSMF [1]  - 提供读Microsoft Outlook格式档案的功能。

2.4 创建方法:写excel

public static void createExcel()throws Exception{
    String[] rowHeads={"sid","sname","sage","sdy","sbirthday","score","realName"};
    //1 创建工作薄
    HSSFWorkbook book=new HSSFWorkbook();
    //2 创建一个sheet表格对象
    HSSFSheet sheet=book.createSheet("Student");
    //3 创建第一列:列标题
    HSSFRow row1=sheet.createRow(0);
    //4 创建标题的单元格
    for (int i = 0; i < rowHeads.length; i++) {
        HSSFCell celli=row1.createCell(i);
        celli.setCellValue(rowHeads[i]);
    }

    //5 创建列 写入数据
    List<Student> list=new ArrayList<Student>();
    for (int i = 0; i <10; i++) {
        list.add(new Student(
            (int)(Math.random()*1000+2000), 
            UUID.randomUUID().toString().substring(1, 5),
            (int)(Math.random()*10+15), 
            Math.random()>0.5, 
            new Date(2020-1900, (int)(Math.random()*12+1), (int)(Math.random()*30+1)),
            (int)(Math.random()*1000)/10.0f, 
            "无名氏"+i,
            null, null));
    }
    for (int j = 0; j < list.size(); j++) {
        HSSFRow rowj=sheet.createRow(j+1);
        Student stu=list.get(j);
        rowj.createCell(0).setCellValue(stu.getSid());
        rowj.createCell(1).setCellValue(stu.getSname());
        rowj.createCell(2).setCellValue(stu.getSage());
        rowj.createCell(3).setCellValue(stu.getSdy());
        //创建一个日期格式cellstyle
        CellStyle dateStyle=book.createCellStyle();
        dateStyle.setDataFormat(book.createDataFormat().getFormat("yyyy-MM-dd"));
        HSSFCell cell4=rowj.createCell(4);
        cell4.setCellStyle(dateStyle);
        cell4.setCellValue(stu.getSbirthday());
        rowj.createCell(5).setCellValue(stu.getScore());
        rowj.createCell(6).setCellValue(stu.getRealName());
    }
    //6 把book写道目的文件中
    book.write(new File("e:\\poi\\student_1.xls"));
    book.close();
}

2.5 创建方法:读excel:把excel中数据每行读成一个对象

  • 规则1:表格名必须是类名
  • 规则2:列标题必须是属性名
//读取excel文件
public static  List<Object> readExcel(File file,String className)throws Exception{
    //1 创建工作薄:读取源文件
    HSSFWorkbook book=new HSSFWorkbook(new FileInputStream(file));
    //2 获取第一个表格
    HSSFSheet sheet=book.getSheet(className);
    //3 获取第一行:列标题  对应的时类的属性名
    HSSFRow row1=sheet.getRow(0);
    //创建一个数组存储属性名
    List<String> fieldNames=new ArrayList<>();
    Iterator<Cell> it=row1.cellIterator();
    while(it.hasNext()){
        Cell cell=it.next();
        fieldNames.add(cell.getStringCellValue());//存储列明:属性名
    }
    //遍历其他行
    List<Object> listObj=new ArrayList<>();
    Class cla=Class.forName("com.zhiyou100.entity."+className);
    for (int i = 1; i < sheet.getLastRowNum(); i++) {
        HSSFRow rowi=sheet.getRow(i);
        //每行对应一个className类型的对象
        Object obj=cla.newInstance();
        for (int j = 0; j <rowi.getLastCellNum(); j++) {
            Object fieldValue;
            HSSFCell cellij=rowi.getCell(j);
            //获取其值
            //System.out.println(cellij.getCellStyle()+":"+cellij.getCellType()+":::"+j);
            if(cellij.getCellType()==CellType.BOOLEAN){
                fieldValue=cellij.getBooleanCellValue();
            }else if(cellij.getCellType()==CellType.NUMERIC){
                fieldValue=cellij.getNumericCellValue();
            }else{
                fieldValue=cellij.getStringCellValue();
            }
            //把值赋值给obj的属性
            Field fieldj=cla.getDeclaredField(fieldNames.get(j));
            fieldj.setAccessible(true);
            fieldValue=changeValue(fieldj,fieldValue);//
            fieldj.set(obj, fieldValue);
        }
        listObj.add(obj);
    }
    book.close();
    return listObj;
}
//把value转换为field对应的类型:
private static Object changeValue(Field field,Object value){
    Class type=field.getType();
    if(type==int.class||type==Integer.class){
        return (int)((double)value);
    }
    if(type==short.class||type==Short.class){
        return (short)((double)value);
    }
    if(type==byte.class||type==Byte.class){
        return (byte)((double)value);
    }
    if(type==long.class||type==Long.class){
        return (long)((double)value);
    }
    if(type==float.class||type==Float.class){
        return (float)((double)value);
    }
    if(type==java.util.Date.class){
        return new Date((long)((double)value));
    }
    return value;
}

3 POI作业

3.1 创建poi工具类::实现通用化 可以操作任意类型

package com.zhiyou100.util;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;

import com.zhiyou100.entity.Student;
import com.zhiyou100.entity.Teacher;

public class PoiUtil {
	public static void main(String[] args) throws Exception{
//		Object obj="1234";
//		System.out.println(obj.getClass());
		
//		List<Object> list=new ArrayList<Object>();
//		for (int i = 0; i <10; i++) {
//			list.add(new Student(
//					(int)(Math.random()*1000+2000), 
//					UUID.randomUUID().toString().substring(1, 5),
//					(int)(Math.random()*10+15), 
//					Math.random()>0.5, 
//					new Date(2020-1900, (int)(Math.random()*12+1), (int)(Math.random()*30+1)),
//					(int)(Math.random()*1000)/10.0f, 
//					"无名氏"+i,
//					i+"123", i+"1.jpg")); 
//		}
//		createExcel(list,"学生信息表2.xls");
		
		List<Object> list=new ArrayList<Object>();
		for (int i = 0; i <10; i++) {
			list.add(
					  new Teacher(
							  i+100, 
							  UUID.randomUUID().toString().substring(0, 5), 
							  Math.random()>0.5?"男":"女")); 
		}
		createExcel(list,"老师信息表1.xls");
		
	}
	//创建excel文件
	//public static void createExcel(List<Object>,File file)throws Exception{
	//使用反射把list中的对象写成表格的行
	//表格标题是对象的类名
	//表格列标题是属性名
	public static void createExcel(List<Object> list,String fileName)throws Exception{
		Class cla=list.get(0).getClass();
		//1 创建工作薄:
		HSSFWorkbook book=new HSSFWorkbook();
		//2 创建sheet:表格对象
		HSSFSheet sheet=book.createSheet(cla.getSimpleName());
		//3 创建第一行:列标题
		HSSFRow row0=sheet.createRow(0);
		Field[] fields=cla.getDeclaredFields();//对象有多少个属性  表格就有多少列
		for (int i = 0; i < fields.length; i++) {
			Field field=fields[i];
			field.setAccessible(true);
			String fieldName=field.getName();
			row0.createCell(i).setCellValue(fieldName);
		}
		//4 每个对象对应写成一行
		for (int i = 0; i <list.size(); i++) {
			Object obj=list.get(i);
			//创建行
			HSSFRow rowi=sheet.createRow(i+1);
			for (int j = 0; j < fields.length; j++) {
				Field field=fields[j];
				Object fieldValue=field.get(obj);//获取属性的值
				HSSFCell cellij=rowi.createCell(j);
				if(field.getType()==Date.class){
					CellStyle dateStyle=book.createCellStyle();
					dateStyle.setDataFormat(book.createDataFormat().getFormat("yyyy-MM-dd"));
					cellij.setCellStyle(dateStyle);
				}
				//cellij.setCellValue(fieldValue);
				setCellValue(field,fieldValue,cellij);
			}
		}
		book.write(new File("E:\\poi",fileName));
		book.close();
		
	}
	     //根据filed的类型把Object类型的值 转换为Field类型的值  然后给cell设置文本内容
    private static void setCellValue(Field field,Object value,HSSFCell cell){
    	    //需要的类型:boolean  string date double
			Class type=field.getType();
			if(type==int.class||type==Integer.class){
				   cell.setCellValue((Integer)value);
			}else if(type==short.class||type==Short.class){
				   cell.setCellValue((Short)value);
			}else if(type==long.class||type==Long.class){
				   cell.setCellValue((Long)value);
			}else if(type==boolean.class||type==Boolean.class){
				   cell.setCellValue((Boolean)value);
			}else if(type==float.class||type==Float.class){
				   cell.setCellValue((Float)value);
			}else if(type==char.class||type==Character.class){
				   cell.setCellValue((Character)value);
			}else if(type==String.class){
				   cell.setCellValue((String)value);
			}else if(type==byte.class||type==Byte.class){
				   cell.setCellValue((Byte)value);
			}else if(type==double.class||type==Double.class){
				   cell.setCellValue((Double)value);
			}else if(type==Date.class){
				   cell.setCellValue((Date)value);
			}else{
				throw new RuntimeException(type+"是不支持的类型!");
			}
			
		}

	//读取excel文件
	public static  List<Object> readExcel(File file,String className)throws Exception{
		//1 创建工作薄:读取源文件
		HSSFWorkbook book=new HSSFWorkbook(new FileInputStream(file));
		//2 获取第一个表格
		HSSFSheet sheet=book.getSheet(className);
		//3 获取第一行:列标题  对应的时类的属性名
		HSSFRow row1=sheet.getRow(0);
		//创建一个数组存储属性名
		List<String> fieldNames=new ArrayList<>();
		Iterator<Cell> it=row1.cellIterator();
		while(it.hasNext()){
			Cell cell=it.next();
			fieldNames.add(cell.getStringCellValue());//存储列明:属性名
		}
		//遍历其他行
	    List<Object> listObj=new ArrayList<>();
	    Class cla=Class.forName("com.zhiyou100.entity."+className);
	    for (int i = 1; i < sheet.getLastRowNum(); i++) {
	    	HSSFRow rowi=sheet.getRow(i);
	    	//每行对应一个className类型的对象
	    	Object obj=cla.newInstance();
	    	for (int j = 0; j <rowi.getLastCellNum(); j++) {
	    		 Object fieldValue;
				 HSSFCell cellij=rowi.getCell(j);
				 //获取其值
				 //System.out.println(cellij.getCellStyle()+":"+cellij.getCellType()+":::"+j);
				 if(cellij.getCellType()==CellType.BOOLEAN){
					 fieldValue=cellij.getBooleanCellValue();
				 }else if(cellij.getCellType()==CellType.NUMERIC){
					 fieldValue=cellij.getNumericCellValue();
				 }else{
					 fieldValue=cellij.getStringCellValue();
				 }
				 //把值赋值给obj的属性
				 Field fieldj=cla.getDeclaredField(fieldNames.get(j));
				 fieldj.setAccessible(true);
				 fieldValue=changeValue(fieldj,fieldValue);//
				 fieldj.set(obj, fieldValue);
			}
	    	listObj.add(obj);
		}
	    book.close();
	    return listObj;
	}
	//把value转换为field对应的类型:
	private static Object changeValue(Field field,Object value){
		Class type=field.getType();
		if(type==int.class||type==Integer.class){
			return (int)((double)value);
		}
		if(type==short.class||type==Short.class){
			return (short)((double)value);
		}
		if(type==byte.class||type==Byte.class){
			return (byte)((double)value);
		}
		if(type==long.class||type==Long.class){
			return (long)((double)value);
		}
		if(type==float.class||type==Float.class){
			return (float)((double)value);
		}
		if(type==java.util.Date.class){
			return new Date((long)((double)value));
		}
		return value;
	}
}

3.2 jsp页面:student_manager02.jsp

<h1>POI操作</h1>
<form action="<c:url value='/student/uploadExcel.action'/>" method="post" enctype="multipart/form-data">
    <input type="file" name="studentSheet"/>
    <input type="submit" value="excel表格上传"/>
</form><br/>
<a href="<c:url value='/student/downloadExcel.action'/>" >下载学生信息生成excel表格</a>

3.3 action

@RequestMapping("/uploadExcel.action")
public String uploadExcelMethod(@RequestParam("studentSheet") MultipartFile studentSheet,HttpServletRequest req)throws Exception{
    //List<Object> readExcel(File file,String className)
    File muDi=new File(studentSheet.getOriginalFilename());//创建一个目的文件 来保存上传的excel文件
    studentSheet.transferTo(muDi);
    //读取文件中的信息
    List<Object> list=PoiUtil.readExcel(muDi, "Student");
    //把list中的所有对象的信息保存到数据库中
    for (Object object : list) {
        Student stu=(Student)object;
        studentService.addOne(stu);
    }
    req.setAttribute("message", "学生信息的excel表格上传成功!");
    return "forward:/student/getAllFenYe.action";
}

@RequestMapping("/downloadExcel.action")
public ResponseEntity<byte[]> downloadExcelMethod(HttpServletRequest req)throws Exception{
    //获取所有学生的信息
    List<Student> list=studentService.getAll();
    List<Object> listObj=new ArrayList<Object>();
    for (Student s : list) {
        listObj.add(s);
    }
    //创建excel文件
    String fileName=System.currentTimeMillis()+"_学生信息表.xls";
    PoiUtil.createExcel(listObj, fileName);
    File yuan=new File("E:\\poi",fileName);

    //获取文件的类型
    String type=req.getServletContext().getMimeType(fileName);

    byte[] arr=FileUtils.readFileToByteArray(yuan);

    //创建heander对象  响应头
    HttpHeaders headers=new HttpHeaders();
    headers.set("Content-Type", type);
    headers.set("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "utf-8"));

    //获取源文件
    //context.get
    ResponseEntity<byte[]>  entity=new ResponseEntity<byte[]>(arr,headers,HttpStatus.OK);
    return entity;
}

3.4 有待优化的地方

  • poi工具类中excel文件的目录 应该设置为servletcontent的初始化参数
  • poi工具类应该指定为泛型类:这样写的参数为List 读的返回值为List
  • poi中两个判断类型的方法 太low了 但没有更好的方法

4 实现事务管理

4.1在spring核心配置文件中添加事务自动注册的标签

<?xml version="1.0" encoding="UTF-8"?>
<beans 	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/aop 
	http://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/tx 
	http://www.springframework.org/schema/tx/spring-tx.xsd
	http://www.springframework.org/schema/mvc 
	http://www.springframework.org/schema/mvc/spring-mvc.xsd">
     <!--添加tx标签的命名空间和xsd文件-->
	 <!-- 开启事务注册驱动 -->
	 <tx:annotation-driven/>
	 <!--3配置事务管理bean -->
	 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	     <property name="dataSource" ref="ds"/>
	 </bean>
</beans>

4.2 只在springmvc配置文件中注册扫描action包 在spring中注册扫描service包

  • spring_config.xml
<!-- 1通过context标签扫描包 -->
<context:component-scan base-package="com.zhiyou100.service"/>
  • springmvc_config.xml
<!-- 1通过context标签扫描包 -->
<context:component-scan base-package="com.zhiyou100.action"/>

4.3 更改添加的代码 让所有的添加都抛出异常: 并添加注解Transactional

@Transactional
public int addOne(Student stu) {
    stu.setSpwd(MD5.getInstance().getMD5(stu.getSpwd()));
    int hang=studentMapper.addOne(stu);
    Student studentDb=studentMapper.getOneBySname(stu.getSname());
    if(studentDb!=null){
        throw new StudentCrudException("学生名字错误!");
    }

    return hang;
}

4.4 测试发现

出现异常:数据库没有添加成功
去掉注解:出现异常  数据库添加成功
posted @ 2021-12-02 22:51  RenVei  阅读(72)  评论(0编辑  收藏  举报