第一次在这里分享一个小的项目,希望对大家有所帮助。中间部分是自己的经历,最后是感悟,赶时间可以直接调到最后(*^▽^*)
本次结对编程要求是运用之前写的四则运算java代码,写一个可视化界面,实现可以自主控制运算符数量,何种类型运算,数值范围等内容,可以在线答题,判题等功能。这一次的编程经历大概如下:
前期,我们两个人进行讨论,确定用户需求,敲定界面大体内容,传递参数等细节。下面是我们的pdf文档部分截图:
我们确定,前后台分离做这一次项目,将我们的代码放在服务器上,可以远程访问。访问http://94.191.30.171:8080/collaboration/index.html可以查看效果。
之后进行实际开发,下面是我们定下来的接口及参数
①首页需要使用ajax传递题目数量(questionNum),数值范围(较小数是randomNum1,较大数是randomNum2),运算符数量(operationNum),有无括号(isBracket),有无分数(isFraction),有无乘除(isFourOperation),这些参数全部是int类型。访问接口(url):http://94.191.30.171:8080/collaboration/admin/start
之后后台会以json格式返回其生成题目,命名为"questionList"
左图为传递的参数的格式,右图为出题页面
②之后跳转到下一个答题页面进行题目作答,前端将后端传递的题目依次展示,在前端完成答题后比较答案与作答情况,进行正误判定。
左图为题目界面,在输入框中输入答案
右图为判题和成绩页面,点击提交答案之后,对每道题答案进行判断,同时给出分数(每道题2分)和时间,同时下方按钮切换为查看文件,便于跳转至下一个文件查看页面
提交答案按钮需要传递参数为数组,包含错误题目,访问接口(url):http://94.191.30.171:8080/collaboration/admin/upload
查看文件按钮没有参数传递,直接获取文件名列表为了下载,
访问接口(url):http://94.191.30.171:8080/collaboration/admin/getFile
- 时间是通过在点击开始出题时,后台生成当时时间startTime,在提交答案之后,后台再产生当时时间endTime,将两个时间传递到前台,前台经过计算和格式转换之后,展示在页面头部;
- 分数是在判断正误时,通过计数的方式,得到正确的题目数量,从而转换为分数
- 错题列表是在判断正误时,将错误的题目传递到arr数组之中,通过list的json形式发给后台
上图为核心代码
③最后会选择提交错题给后端,生成错题记录文件,供用户下载(下载列表)。
下载时需要传递点击链接对应数据库id,找到存储于数据库的文件名,再去下载对应的文件。
访问接口(url):http://94.191.30.171:8080/collaboration/admin/download
上图为文件下载界面,后台传入错题文件列表,点击之后下载下来查看具体情况。
点击返回出题界面之后,直接返回最初的出题界面,至此完成一次出题,答题,判题,统计分数,生成文件,文件下载的全流程
总结:最后,谈一下我们在开发这个项目时的心得感悟。这个项目我们只按照老师要求做了最基础的功能,完成了出题,做题,判题,查题。
前端:主要是通过json传递字符串数组到后台,我们的交互出现了问题。第一次是后台接受使用注解出了问题,第二次是前端传值的List序号不是按照0123排列的,最后在层层改进我们终于成功。
后端:我主要说一下文件上传下载
一、最开始的接触——Factory建立文件工厂上传下载
博客学习:http://www.cnblogs.com/xdp-gacl/p/4200090.html
大致思路:
二、其次的学习——java实现文件上传下载
慕课学习
大致思路:将传递来的文件流写入过渡文件中,再从中截取有用字段写入最终文件,保存。
1.我们要接受前台传过来的文件流
InputStream fileSource = request.getInputStream();
2.我们要有一个过渡的文件
String tempFileName = "D:/tempFile"; File tempFile = new File(tempFileName);
3.然后将接受的前台文件流输入到过渡文件中(OutputStream是将数据写入文件中)
FileOutputStream outputStream = new FileOutputStream(tempFile);
byte b[] = new byte[1024];
int n; //读取文件,只要没结束,就往输出流中写入,即将上传文件写入中间文件中去。
while((n = fileSource.read(b)) != -1){
outputStream.write(b,0,n); //从第0个位置读取到n个位置,每次读取1204个字节
} //关闭输入输出流
outputStream.close();
fileSource.close();
4.我们要从过渡文档中找到文件名
RandomAccessFile randomFile = new RandomAccessFile(tempFile,"r"); //以只读方式打开tempFile randomFile.readLine(); //读第一行
String str = randomFile.readLine(); //从第二行开始读
int beginIndex = str.lastIndexOf("=")+2; //找到开始位置,从最后一个=之后两个位置开始
int endIndex = str.lastIndexOf("\""); //找到结束位置,最后一个\位置结束
String filename = str.substring(beginIndex,endIndex); //截取这之间的字符串成为文件名字
5.我们从过渡文档中截取有用文件信息,作为最后文件的内容
randomFile.seek(0); //指针回到开始位置
long startPosition = 0;
int i = 1;
while((n = randomFile.readByte()) != -1 && i <= 4){ //读取文件0---4行的数据
if(n == '\n'){
startPosition = randomFile.getFilePointer(); //获取指针当前位置
i++;
}
}
startPosition = startPosition - 1;
randomFile.seek(randomFile.length()); //指针去到文件最后位置
long endPosition = randomFile.getFilePointer();
int j = 1;
while (endPosition >= 0 && j<= 2){ //获取最后两行的数据
endPosition--;
randomFile.seek(endPosition);
if(randomFile.readByte() == '\n'){
j++;
}
}
endPosition = endPosition - 1;
6.我们要有一个最后保存的文件
//根据servlet的位置寻找保存文件的文件夹
String realPath = getServletContext().getRealPath("/") + "images";
File fileupload = new File(realPath);
if(!fileupload.exists()){
fileupload.mkdir(); //不存在就新建文件夹
}
File saveFile = new File(realPath,filename);
7.向最终文件写入内容
//新建文件只读?rw读取与写入
RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile,"rw"); randomFile.seek(startPosition); //将指针移到开始位置
while(startPosition < endPosition){
randomAccessFile.write(randomFile.readByte()); //往最终文件写入内容
startPosition = randomFile.getFilePointer(); //获取当前指针位置
}
//关闭文件流
randomAccessFile.close();
randomFile.close();
8.删除掉中间文件,结束这一次的文件传输
tempFile.delete();
三、最后的升级——spring框架实现文件上传下载
慕课学习+博客见解:https://blog.csdn.net/qian_ch/article/details/69258465
大致思路:利用SpringMVC框架自带的功能进行文件上传下载
1.新建maven项目,搭建起Spring框架。
在maven中引入Spring的jar包,尤其注意文件上传下载需要commons-io,commons-fileupload两个jar包。
PS:在开发过程中我遇到了ClassNotFound的问题,这时候根据错误信息找到class在哪一个jar里,去到out文件lib目录下看有没有实际生成这个jar包,没有就需要手动导入。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!--图片处理-->
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
2.新建spring的xml,由web.xml设置访问路径。
在spring的xml文件中配置文件上传下载核心——MultipartResolver
<!--文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<!-- 1024*1024*20=20M -->
<property name="maxUploadSize" value="20971520"></property>
<property name="maxInMemorySize" value="20971520"></property>
</bean>
2.新建spring的xml,由web.xml设置访问路径。
在spring的xml文件中配置文件上传下载核心——MultipartResolver
<!--文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8">
</property>
<!-- 1024*1024*20=20M -->
<property name="maxUploadSize" value="20971520">
</property>
<property name="maxInMemorySize" value="20971520">
</property>
</bean>
3.开始文件的上传
(1)利用MultipartResolver接收请求中的文件流
(2)使用MultipartFile的属性实现文件上传
//上传文件会自动绑定到MultipartFile中
@RequestMapping(value="/upload",method=RequestMethod.POST)
public Map<String,Object> upload(HttpServletRequest request,
@RequestParam("file") MultipartFile file) throws Exception {
Map<String,Object> map = new HashMap<>();
//如果文件不为空,写入上传路径
if(!file.isEmpty()) {
//上传文件路径
//String path = request.getServletContext().getRealPath("/images/");
String path = "D:/homework/image/answer/2";
//上传文件名
String filename = file.getOriginalFilename();
File filepath = new File(path,filename);
//判断路径是否存在,如果不存在就创建一个
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
//将上传文件保存到一个目标文件当中
file.transferTo(new File(path + File.separator + filename));
map.put("success",true);
}
else{
map.put("success",false);
}
return map;
}