java实训小项目6_实训项目

本文是作者在为期3周的Java实训中,使用SpringBoot、Mybatis进行后端开发的心得体会,包括Maven、Mybatis的使用体验,SpringBoot的5层框架解析,以及文件上传、Excel解析、文件下载和Word模板处理的详细实现。
摘要由CSDN通过智能技术生成

layout: post

title: 实训项目

date: 2020-12-6

author: XiaoJia849

categories:

- 开发部

tags:

- 后端

- springboot

- 文件处理

项目实训已经度过3周,三周内被迫学会了springboot 和mybatis的基本使用,以下是我的一点总结。以及对文件的操作记录。

Maven

Mybatis

Springboot

上传excel与解析

上传任意类型文件且保存

浏览器下载文件

java处理word模板

Maven

Maven是个好东西,如果在配置pom.xml时不经常爆红的话。

Maven在我的理解中是一个jar包管理库,使用Maven让我无需导入jar包,如果需要使用这个jar包时,只需要在pom.xml内写入依赖即可,非常方便。

Mybatis

Mybatis内写sql语句调用数据库的资源,把所有涉及与数据库交互的过程全部封装在mapper内的xml文件中,但是对于初次接触MyBatis的我而言不是很友好。当我需要写嵌套查询时,发现此时仅仅是更改sql语句只会引发一串报错,这也就意味着,当sql语句跳出了简简单单的一层插入,更新,查询时,难度大幅度上升了。其实只是我太菜了,要写嵌套查询还是很方便的。

例子

insert into pro (Pid,Pname,Pcontent,Pnum)

values (#{Pid},#{Pname},#{Pcontent},#{Pnum})

select MAX(Pid)

from pro;

select

Pid,Pname,Pcontent,Pnum,

from pro;

update stu_team_pro

set Pid=#{pid}

where GroupId=#{groupId};

和sql里面写嵌套查询没啥区别,我也不知道为什么我在网上搜到的那么复杂ㄟ( ▔, ▔ )ㄏ

总而言之,感谢队友 (_)

Update tea_ans

set Grade=#{Grade}

where Tid=#{Tid} and ReplyId in(

select ReplyId

from scen

where GroupId=#{GroupId}

);

Springboot

Springboot的亮点在于5层框架,把每层的功能分的十分细致。

model层描述对象的属性。

dao层与Mybatis打交道,里面写满各种与数据库相关的方法。

service层则可以将dao层的方法组合起来使用,当要处理的问题简单时,其实并不需要service层。

control层用于和前端进行交互,接收数据,调用dao层或者service层的方法进行处理,处理后将结果返回前端。

config层我只知道可以作为拦截器限制control层与前端的交互。

此外,springboot的优点还在于可以清晰的让每个函数只做一件事,比如说:

函数A要更改数据库,函数B要实现把数据库中的数据拿到前端展示的作用

可是我们要实现的功能是界面上更改数据库传出请求后马上返回到这个页面,要将AB两个函数的功能按顺序使用,那么可以在A函数结束后 return "redirect:/B" ,这样就OK了

之前采用MVC框架写过前后端的代码,那个时候并不知道springboot这么香的存在,哎

上传excel与解析

功能

前端上传excel文件,后端实现获取excel内容,并将对应的内容存入数据库内

要点

上传文件的 jsp要进行以下修改

在jsp的head内和form内都明确上传的数据类型是multipartFile,且限制上传的文件类型为excel

Maven导包使支持POI且2007之后的excel文件处理

在pom.xml内写入以下内容

org.apache.poi

poi-ooxml

3.15

org.apache.poi

poi-scratchpad

3.8

写入以上之后才能使用XSSF

control层内代码实现

@PostMapping("AdminEXC")

public String export(@RequestParam("exc") MultipartFile file,

HttpServletRequest request, HttpServletResponse response) {

try {

// @RequestParam("file") MultipartFile file 是用来接收前端传递过来的文件

// 1.读取文档file并且把数据流形式存放在inputStream内

InputStream inputStream = file.getInputStream();

//定义工作簿,把数据流以excel文件的形式组织起来,形成工作簿

XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);

//定义工作表,工作簿第0页也就是第一张sheet

XSSFSheet xssfSheet;

xssfSheet = xssfWorkbook.getSheetAt(0);

//已知excel第0列内容是专业

//要获取不重复的专业列我采用放入map的方式

Map map= new HashMap();

//定义标题行,第0行为标题行,index = 0

XSSFRow titleRow = xssfSheet.getRow(0);

//xssfSheet无法直接获得一列的元素,所以只能用行的for循环

//获取专业列也即map的key 列

for (int rowIndex = 1; rowIndex < xssfSheet.getPhysicalNumberOfRows(); rowIndex++) {

XSSFRow xssfRow = xssfSheet.getRow(rowIndex);

if (xssfRow.getCell(3) == null) {

continue;

}else{

map.put(xssfRow.getCell(3).getStringCellValue(),1);

}

}

//xssfSheet.getPhysicalNumberOfRows()代表这个工作表的行数,并不一定就等于有文字的部分的行数,所以在进行for循环时,判断对应的值是否为null时十分有必要的

//根据key的排列对value进行从上到下的标号

//标号后存入数据库内

int i=0;

//将专业相关信息插入dept表内

for (Map.Entry entry : map.entrySet()) {

i=i+1;

entry.setValue(i);

//一个数据库插入函数

//把key作为sdept i作为Sdid 插入

proDao.Insdid(i,entry.getKey());

}

//循环取每行的数据,完善学生相关信息

for (int rowIndex = 1; rowIndex < xssfSheet.getPhysicalNumberOfRows(); rowIndex++) {

XSSFRow xssfRow = xssfSheet.getRow(rowIndex);

if (xssfRow.getCell(3) == null) {

continue;

}else{

String sid=xssfRow.getCell(0).getStringCellValue();

String sname=xssfRow.getCell(1).getStringCellValue();

String spwd=sid.substring(0,3)+sid.substring(5,8);

Integer sdid=map.get(xssfRow.getCell(3).getStringCellValue());

proDao.Instu(sid,sname,spwd,sdid);

}

//以上部分为基操,不做描述

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return "Adminfunc";

}

上传任意类型文件且保存

上传文件的 jsp要进行以下修改

xx

hh

在jsp的head内和form内都明确上传的数据类型是multipartFile

@PostMapping("Proupload")

public String Upload(HttpServletRequest request,@RequestParam("xfile") MultipartFile file){

try{

//获取题目id

int pid=Integer.valueOf(request.getParameter("pid"));

//得到文件名

String filename = file.getOriginalFilename();

//得到文件类型

String extFileName = filename.substring(filename.lastIndexOf("." ) +1,filename.length());

//例如上传文件xx.txt

//filename="xx.txt"

//extFileName="txt"

//获取当前所在文件夹的绝对路径realPath

String realpath=request.getSession().getServletContext().getRealPath("/");

//略微修改一下,得到我将把上传的文件夹存入的路径 ——filePath

String filePath=realpath.substring(0,realpath.length()-7)+"resources\\file\\";

String path = filePath + filename;

//以上两者拼接得到一个完整的文件存入的路径

//在这个路径上创建文件

File dest = new File(path);

if (!dest.getParentFile().exists()){

//若此路径不存在则创建目录

dest.getParentFile().mkdir();

}

//将file文件完全复制存入到dest这个文件内

file.transferTo(dest);

//把对应的数据库信息存入

proDao.Inurl(pid,path);

}catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return "Teafunc";

}

浏览器下载文件

jsp内

pom.xml内补充依赖

org.junit.platform

junit-platform-engine

control层

@PostMapping("download")

public static void downFile(HttpServletRequest request, HttpServletResponse response) throws IOException {

//等待被下载的文件的绝对路径

String url="F:\\ne\\AC自动机&TireTree.docx";

//该文件的名字

String filename="AC自动机&TireTree.docx";

//找到该文件

File file=new File(url);

// 文件存在才下载

if (file.exists()) {

OutputStream out = null;

FileInputStream in = null;

try {

// 把文件转化为数据流存储在in内

in = new FileInputStream(file);

// 告诉浏览器下载的方式以及一些设置

// 解决文件名乱码问题,获取浏览器类型,转换对应文件名编码格式,IE要求文件名必须是utf-8, firefo要求是iso-8859-1编码

//获取浏览器信息

String agent = request.getHeader("user-agent");

if (agent.contains("FireFox")) {

//如果是火狐浏览器,则需要转编码

filename = new String(filename.getBytes("UTF-8"), "iso-8859-1");

} else {

//其他的全部设置为UTF-8形式

filename = URLEncoder.encode(filename, "UTF-8");

}

// 设置下载文件的mineType,告诉浏览器下载文件类型

String mineType = request.getServletContext().getMimeType(filename);

//设置相应类型与文件类型一致(因为要下载这个文件)

response.setContentType(mineType);

// 设置一个响应头,无论是否被浏览器解析,都下载

response.setHeader("Content-disposition", "attachment; filename=" + filename);

// 将要下载的文件内容通过输出流写到浏览器

out = response.getOutputStream();

//把输入流的内容全部复制到输出流

int len = 0;

byte[] buffer = new byte[1024];

while ((len = in.read(buffer)) > 0) {

out.write(buffer, 0, len);

}

//复制结束后实现了输出一个一模一样的文件

} catch (IOException e) {

e.printStackTrace();

} finally {

if (out != null) {

out.close();

}

if (in != null) {

in.close();

}

}

}

}

例子

java处理word模板

jsp内

pom.xml内

org.apache.poi

ooxml-schemas

1.4

control层

已知我的模板文件在resources/file/下 stugrade.docx

要在同目录下创建文件xx4.docx

42c159183a90

stugrade.docx

@PostMapping("getGrade")

public static String getGrade(HttpServletRequest request, HttpServletResponse response) throws IOException {

// 获取当前项目的绝对地址

String realpath=request.getSession().getServletContext().getRealPath("/");

String filePath=realpath.substring(0,realpath.length()-7)+"resources\\file\\";

//模板文件地址,下面过程不会更改模板文件

String inputUrl = filePath + "stugrade.docx";

//新生产的文件

String outputUrl=filePath+"xx4.docx";

//在map内按照模板对应位置的英文key补充填写内容value

Map map=new HashMap<>();

map.put("Pname","hhh");

map.put("Tname","hhh");

map.put("student","hhh");

map.put("tea1","hhh");

map.put("grade1","hhh");

map.put("tea2","hhh");

map.put("grade2","hhh");

map.put("time","hhh");

map.put("place","hhh");

map.put("grade","hhh");

try {

//获取word文档解析对象

XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));

//获取文章

Iterator itPara = document.getParagraphsIterator();

while (itPara.hasNext()) {

//获取段落

XWPFParagraph paragraph = (XWPFParagraph) itPara.next();

//获取段落内的最小结构run

List runs = paragraph.getRuns();

for (XWPFRun run : runs) {

//获取文字

String text = run.getText(0);

if (text != null) {

boolean isSetText = false;

//遍历map寻找key

for (Map.Entry entry : map.entrySet()) {

String key = entry.getKey();

if (text.indexOf(key) != -1) {// 在配置文件中有这个关键字对应的键

isSetText = true;

Object value = entry.getValue();

if (value instanceof String) {

// 文本替换

if (text.contains(key)) {

text = text.replace(key, value.toString());

}

}

}

}

if (isSetText) {

run.setText(text, 0);

}

}

}

}

//创建输出文件

File file = new File(outputUrl);

FileOutputStream stream = new FileOutputStream(file);

//把document的内容写入到stream对应的文件file内

document.write(stream);

stream.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return "Adminfunc";

}

备注

参考

项目

这个是我们小组6个人的作品,如果允许的话,项目源码将在这个实训结束后上传github网址用于分享 不了,还是算了吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值