学习过程 | SSM框架实现基本的文件上传下载功能
(只用看image相关的文件,paper和user不用)
1.项目结构
项目结构内容解释(按照构建顺序)
1.pojo:存放项目涉及得到实体类,实体的属性和setter,getter方法
package com.pojo;
public class Image {
private int id;
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
2.dao:存放对数据库操作的接口
package com.dao;
import com.pojo.Image;
import java.util.List;
public interface ImageDao {
int add(String content);
int deleteById(int id);
List<Image> queryAllImage();
String queryImageById(int id);
}
3.service:存放对pojo实体类的操作接口,与dao接口相对应
package com.service;
import com.pojo.Image;
import java.util.List;
public interface ImageService {
List<Image> queryAllImage();
int add(Image image);
int deleteById(int id);
String queryImageById(int id);
}
4.service下的impl包:存放service下接口的实现类,每个方法返回对dao中接口方法的调用,注意注解不要丢了
package com.service.impl;
import com.dao.ImageDao;
import com.pojo.Image;
import com.service.ImageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ImageServiceImpl implements ImageService {
@Autowired
private ImageDao imageDao;
@Override
public int add(Image image) {
return imageDao.add(image.getContent());
}
@Override
public int deleteById(int id) {
return imageDao.deleteById(id);
}
@Override
public List<Image> queryAllImage() {
return imageDao.queryAllImage();
}
public String queryImageById(int id) {
return imageDao.queryImageById(id);
}
}
5.mapper:对dao中方法的实现,对数据库进行增删改除操作,具体细节可以查看MyBatis教程
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.ImageDao">
<resultMap type="Image" id="imageResultMap" >
<!--property是类中的属性,column是数据库中的列-->
<id property="id" column="image_id"/>
<result property="content" column="image_content"/>
</resultMap>
<insert id="add" parameterType="Image">
INSERT INTO image(image_content)
VALUES (#{content})
</insert>
<delete id="deleteById" parameterType="int">
delete from image where image_id = #{id}
</delete>
<select id="queryAllImage" resultMap="imageResultMap">
select image_id,image_content from image
</select>
<select id="queryImageById" resultType="String" parameterType="int">
select image_content from image where image_id=#{id};
</select>
</mapper>
6.配置文件
spring-dao.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置整合mybatis过程 -->
<!-- 1.配置数据库相关参数properties的属性:${url} -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 2.数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置连接池属性 -->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- 3.配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 扫描pojo包 使用别名 -->
<property name="typeAliasesPackage" value="com.pojo"/>
<!-- 扫描sql配置文件:mapper需要的xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.dao"/>
</bean>
</beans>
spring-mvc.xml
<?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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解模式 -->
<!-- 简化配置:
(1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter
(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持
-->
<mvc:annotation-driven />
<!-- 2.静态资源默认servlet配置
(1)加入对静态资源的处理:js,gif,png
(2)允许使用"/"做整体映射
-->
<mvc:default-servlet-handler/>
<!-- 3.配置jsp 显示ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!--200*1024*1024即200M resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="209715200" />
<property name="defaultEncoding" value="UTF-8" />
<property name="resolveLazily" value="true" />
</bean>
<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="com.controller" />
</beans>
spring-service.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.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">
<!-- 扫描service包下所有使用注解的类型 -->
<context:component-scan base-package="com.service" />
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置基于注解的声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/papersystem?useSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=password
log4j.properties
log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
mybatis-congif.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置全局属性 -->
<settings>
<!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
<setting name="useGeneratedKeys" value="true" />
<!-- 使用列别名替换列名 默认:true -->
<setting name="useColumnLabel" value="true" />
<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
</configuration>
6.jsp页面
index.jsp
<%--JSP指令page:定义页面的依赖属性--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%--隐含对象pageContext:PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问--%>
<%
pageContext.setAttribute("path", request.getContextPath());
%>
<!DOCTYPE HTML>
<html>
<head>
<title>首页</title>
<style type="text/css">
a {
text-decoration: none;
color: black;
font-size: 18px;
}
h3 {
width: 180px;
height: 38px;
margin: 100px auto;
text-align: center;
line-height: 38px;
background: deepskyblue;
border-radius: 4px;
}
</style>
</head>
<body>
<%--bootstrap网格的基本结构--%>
<div class="container">
<%--clearfix清除浮动--%>
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
基于SSM框架的管理系统:简单实现增、删、改、查。
</h1>
</div>
</div>
</div>
</div>
<br><br>
<h3>
<a href="${path }/image/allImage">点击进入管理页面</a>
</h3>
</body>
</html>
allImage.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2019/2/22
Time: 15:56
To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
pageContext.setAttribute("path", request.getContextPath());
%>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>allImage</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column" >
<div class="page_header">
<h1>图片列表</h1>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table">
<thead>
<tr>
<td>序号</td>
<td>内容</td>
<td>图片显示</td>
<td>删除</td>
<td>下载</td>
</tr>
</thead>
<tbody>
<c:forEach var="image" items="${requestScope.get('list1')}" varStatus="status1">
<tr>
<td>${image.id}</td>
<td>${image.content}</td>
<td>
<img id="images" alt="" width="100" height="100" src="/myImage1/${image.content }">
</td>
<td><a href="${path}/image/delete/${image.id}">删除</a> </td>
<td><a href="${path}/image/down/${image.id }">下载</a> </td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
<%-- 存项目中的图片 <c:forEach var="b" items="${list1}">
<img src="http://localhost:8080/first/${b.content}">
</c:forEach>--%>
<div class="row clearfix">
<div class="col-md-12 column">
<a href="${path}/image/addImage"><button>增加</button></a>
</div>
</div>
</div>
</body>
</html>
addImage.jsp
<%--
Created by IntelliJ IDEA.
User: lenovo
Date: 2018/4/7
Time: 16:45
To change this template use File | Settings | File Templates.
--%>
<%--JSP指令taglib:引入标签库的定义,可以是自定义标签,下面是引入核心标签库--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
out.print(path);
/*path = ""*/
/*basepath=http://localhost:8080/*/
%>
<html>
<head>
<title>新增论文</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
基于SSM框架的管理系统:简单实现增、删、改、查。
</h1>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>新增论文</small>
</h1>
</div>
</div>
</div>
<form action="" name="userForm">
<%--这里的name是属性名--%>
论文名称:<input type="text" name="paperName"><br><br><br>
论文数量:<input type="text" name="paperNum"><br><br><br>
论文详情:<input type="text" name="paperDetail"><br><br><br>
<input type="button" value="添加" onclick="addPaper()">
</form>
<script type="text/javascript">
function addPaper() {
var form = document.forms[0];
form.action = "<%=basePath %>paper/addPaper";
form.method = "post";
form.submit();
}
</script>
</div>
7.controller
imageController
package com.controller;
import com.pojo.Image;
import com.service.ImageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.UUID;
@Controller
@RequestMapping("/image")
public class ImageController {
@Autowired
private ImageService imageService;
@RequestMapping("/allImage")
public String queryAllImage(Model model) {
List<Image> list1 = imageService.queryAllImage();
System.out.println(list1.size());
for (Image i:list1
) {
System.out.println(i.getContent()+","+i.getId());
}
model.addAttribute("list1", list1);
return "allImage";
}
@RequestMapping("/addImage")
public String addImage() {
return "addImage";
}
@RequestMapping(value="/doAddImage",method = RequestMethod.POST)
public String doAddImage(@RequestParam(value = "file") MultipartFile[] file, Image image, HttpServletRequest request) throws IOException {
/**
* 图片上传到项目
*/
/*
//上传后的地址,注意("/upload")是表示文件上传后的目标文件夹
String realPath = request.getSession().getServletContext().getRealPath("/upload");
System.out.println("=========打印文件上传的路径"+realPath);
for (int i = 0; i < file.length; i++) {
//获取文件名
String filename = file[i].getOriginalFilename();
//获取文件后缀名
String extensionname = filename.substring(filename.lastIndexOf(".") + 1);
//给上传的文件起别名,有很多种方式
String newFilename=String.valueOf(System.currentTimeMillis())+"."+extensionname;
//创建File对象,传入目标路径参数,和新的文件别名
File dir=new File(realPath,newFilename);
if (!dir.exists()){//如果dir代表的文件不存在,则创建它,
dir.mkdirs();//
}
//如果存在则直接执行下面操作
file[i].transferTo(dir);//将上传的实体文件复制到指定目录upload下
image.setContent(newFilename);//将文件名赋值给实体类,然后一并存到数据库
imageService.add(image);//调用后台方法,将对象存进数据库
}
*/
/**
* 图片上传到本地
*/
//图片上传成功后,将图片的地址写到数据库
String filePath = "d:\\myImage1";
for (int i = 0; i < file.length; i++) {
//获取文件名
String filename = file[i].getOriginalFilename();
//获取文件后缀名
String extensionname = filename.substring(filename.lastIndexOf(".") + 1);
//给上传的文件起别名,有很多种方式
String newFileName=String.valueOf(System.currentTimeMillis())+"."+extensionname;
//封装上传文件位置的全路径,就是硬盘路径+文件名
File targetFile = new File(filePath,newFileName);
System.out.println("!!!!!!!========="+targetFile);
if (!targetFile.exists()){//如果dir代表的文件不存在,则创建它,
targetFile.mkdirs();
}
//把本地文件上传到已经封装好的文件位置的全路径就是上面的targetFile
file[i].transferTo(targetFile);
image.setContent(newFileName);//文件名保存到实体类对应属性上
//保存商品
imageService.add(image);
}
return "redirect:/image/allImage";
}
/*文件下载*/
@RequestMapping("/down/{id}")
public void download(@PathVariable("id") int id, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//根据选择文件的编号,查找到相应的文件名字
String beginname = imageService.queryImageById(id);
System.out.println("@@@@@@@@@@@@@@@@@@@0" + beginname);
//生成文件的存储位置
String fileName = "d:\\myImage1"+"/"+ beginname;
System.out.println("!!!!!!!!!!!!!!!!!" + fileName);
//封装为完整的文件路径
File file = new File(fileName);
//如果文件存在的话
if (file.exists()) {
//获取输入流
InputStream bis = new BufferedInputStream(new FileInputStream(file));
//假如以中文名下载的话
String filename = beginname;
//转码,免得文件名中文乱码
filename = URLEncoder.encode(filename, "UTF-8");
//设置文件下载头
response.addHeader("Content-Disposition", "attachment;filename=" + filename);
//1.设置文件ContentType类型,这样设置,会自动判断下载文件类型
response.setContentType("multipart/form-data");
/*getOutputStream获取子程序的输出流*/
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
int len = 0;
while ((len = bis.read()) != -1) {
out.write(len);
/*将缓冲区中的数据写入到输出流中*/
out.flush();
}
out.close();
} else {
//下载的文件不存在
request.setAttribute("errorResult", "文件不存在下载失败!");
RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/01.jsp");
dispatcher.forward(request, response);
}
}
/*根据文件序号删除指定的文件*/
@RequestMapping("/delete/{id}")
public String deleteImageById(@PathVariable("id") int id) {
imageService.deleteById(id);
return "redirect:/image/allImage";
}
}