本文主要讲述了大饼的图片服务器基于servlet创建不同接口并绑定URL,包括ImageServlet和ImageShowServlet。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!--表示在开发阶段需要此依赖,部署到Tomcat后就不需要了-->
<scope>provided</scope>
</dependency>
在最开始设计时我们将功能分为以下几个模块:上传图片,查看图片属性(全部和部分),查看图片内容,删除图片。我们将请求设计成了两种形式,其中上传图片,查看图片属性(全部和部分),删除图片的请求的URL均为./image,查看图片属性和查看图片内容方法相同所以设计请求时将URL部分设计的不一样。
所以我们需要两个类,ServletImage绑定的URL为:./image
,ServletImageShow绑定的URL为:./imageShow
可以在Java目录下创建一个api的包,里面新建两个类ServletImage和ServletImageShow,都继承自HttpServlet
上传图片用的是Post方法,所以重写doPost方法
上传一张图片可以分为以下步骤:
1.获取请求中的图片属性存入数据库
2.将图片存入磁盘
3.告诉客户端上传成功
首先我们要获取到客户端上传的图片信息,这里使用FileUpload来获取文件的信息,首先我们需要导入FileUpload依赖,在pom.xml中加入依赖:
<!--上传文件的第三方仓库FileUpload-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
导入依赖后我们需要:
(1)创建factory对象和fileUpload对象为获取图片信息做准备(固定逻辑)
(2)将获取到的文件信息存到列表items中
(3)获取列表items中第一个文件的信息存入对象fileimage中
(4)在fileiteam中的信息取出分别存储到image中的各种属性中(这个过程中构造出文件存储路径)
(5)调用ImageDao中的存储方法,将image存储到数据库
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
用fileUpload.parseRequest(req)方法来获取请求中的文件信息,返回值为List类型
List<FileItem> items = fileUpload.parseRequest(req);
处理异常try/catch,若代码抛出异常说明在这里解析文件内容存入items时出错了,让其抛出异常信息:
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"请求解析失败\"}");
FileItem fileItem = items.get(0);
Image image = new Image();
image.setImageName(fileItem.getName());//将取出的数据中文件名赋值给ImageName
image.setSize((int) fileItem.getSize());
//获取当前时间作为存储时间,存储于image中的UploadTime
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
image.setUploadTime(simpleDateFormat.format(new Date()));
image.setContentType(fileItem.getContentType());
//构造一个路径:./image+图片名
//但是这个文件存储路径会导致文件名相同时文件路径就会相同,无法存储,
//所以可以在这个路径中加入时间戳(毫秒级)来分开两个文件
image.setPath("./image/"+System.currentTimeMillis()+"_"+fileItem.getName());
image.setMd5("12903421");//当前先写死,后面加上计算md5
ImageDao imageDao = new ImageDao();
imageDao.insert(image);
将 image 的 path 元素内容传给 File 的对象 file (指定文件保存的路径为 image.path),然后将 fileItem 中存储的文件存储在 file 中指定的文件路径中
File file =new File(image.getPath());
fileItem.write(file);
记得处理异常,用try/catch,若执行出错抛出异常说明文件存入磁盘出错,在catch中加入错误信息:
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"写入磁盘失败\"}");
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":true }");
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取图片属性数据存入数据库
//(1)创建一个factory对象和fileUpload对象,为获取图片属性做的准备工作(固定逻辑)
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//(2)fileUpload对象进一步解析,将数据存入items
try {
List<FileItem> items = fileUpload.parseRequest(req);
//此时Itmes已经把图片信息获取到了(此时获取到图片信息的可能不止一个图片的,所以用列表存储)
//(3)将fileUpload解析得到的信息存入image
FileItem fileItem = items.get(0);
//取出items中存储的众多图片中的第一个图片的信息存储于fileItem
Image image = new Image();
image.setImageName(fileItem.getName());//将取出的数据中文件名赋值给ImageName
image.setSize((int) fileItem.getSize());
//获取当前时间作为存储时间,存储于image中的UploadTime
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
image.setUploadTime(simpleDateFormat.format(new Date()));
image.setContentType(fileItem.getContentType());
//构造一个路径:./image+图片名,但是这个文件存储路径会导致文件名相同时文件路径就会相同,无法存储,所以可以在这个路径中加入时间戳(毫秒级)来分开两个文件
image.setPath("./image/"+System.currentTimeMillis()+"_"+fileItem.getName());
image.setMd5("12903421");//当前先写死
//(4)将数据存入数据库,利用imageDao中的insert方法
ImageDao imageDao = new ImageDao();
imageDao.insert(image);
//2.将图片内容存入磁盘
File file =new File(image.getPath());
try {
fileItem.write(file);
} catch (Exception e) {
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"写入磁盘失败\"}");
}
} catch (FileUploadException e) {
//解析失败的情况
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"请求解析失败\"}");
} catch (SQLException e) {
throw new RuntimeException(e);
}
//3.给客户端返回一个结果
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":true }");
}
查看图片属性为使用GET方法,所以需要重写doGet方法
查看图片属性分两种情况:1.查看所有图片属性;2.查看部分图片属性,可以根据请求有没有imageId属性判断为查看什么照片的属性,所以我们需要有两个方法分别为查看全部图片和查看部分图片,用if判断一下imageId是否为空,为空使用查看所图片的方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//将URL中的imageId参数的值赋值给imageId
String imageId = req.getParameter("imageId");
//imageId.equals("") 条件判断语句,检查变量 imageId 是否等于空字符串。
// 如果 imageId 等于空字符串,那么条件为真,执行 if 语句块中的代码;
// 否则,跳过 if 语句块。
if (imageId == null || imageId.equals("")){
//根据设计好的API,imageId为空时为查找全部图片信息
try {
selectAll(req,resp);//(调用下面的查找所有图片的方法)
} catch (SQLException e) {
throw new RuntimeException(e);
}
}else {
try {
selectOneId(imageId,resp);//(调用下面的查找一个图片的方法)
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
private void selectAll(HttpServletRequest req ,HttpServletResponse resp) throws SQLException, IOException {
//1.创建Image对象并查找数据库(查找数据库需要ImageDao类中的selectAll()方法,所以需要先创建imageDao对象)
ImageDao imageDao =new ImageDao();
List<Image> images = imageDao.selectAll();
//2.将gson数组转成Json字符串
//(1)创建一个gson对象
Gson gson = new GsonBuilder().create();
//(2)利用gson.toJson方法将gson转换成json格式的字符串
String jsonData = gson.toJson(images) ;
//3.将Json字符串写入返回值resp中
resp.getWriter().write(jsonData);
}
1.创建列表images(
List< Image >
),用于存储调用ImageDao中的selectAll方法的返回值
2.用new GsonBuilder().create();
创建Gson对象,因为此时查到的数据还是Java对象,要将其以json格式传输给resp,此时就需要用到gson对象
3.将Java对象转换成json格式的String对象gson.toJson(images) ;
4.将转换后得到的json格式的字符串写入resp中resp.getWriter().write(jsonData);
private void selectOneId(String imageId ,HttpServletResponse resp) throws SQLException, IOException {
//1.创建Image对象并查找数据库
ImageDao imageDao = new ImageDao();
Image image = imageDao.selectOneId(Integer.parseInt(imageId));
//2.将gson数组转成Json字符串
//(1)创建一个gson对象
Gson gson = new GsonBuilder().create();
//(2)利用gson.toJson()方法将gson转换成json字符串
String jsonData = gson.toJson(image);
//3.将Json字符串写入返回值resp中
resp.getWriter().write(jsonData);
}
1.创建Image对象image,用于存储调用ImageDao中的selectOneId方法的返回值(传入参数imageId将转为Int类型)
2.用new GsonBuilder().create();
创建Gson对象,因为此时查到的数据还是Java对象,要将其以json格式传输给resp,此时就需要用到gson对象
3.将Java对象转换成json格式的String对象gson.toJson(image);
4.将转换后得到的json格式的字符串写入resp中resp.getWriter().write(jsonData);
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//将URL中的imageId参数的值赋值给imageId
String imageId = req.getParameter("imageId");
//imageId.equals("") 条件判断语句,检查变量 imageId 是否等于空字符串。
// 如果 imageId 等于空字符串,那么条件为真,执行 if 语句块中的代码;
// 否则,跳过 if 语句块。
if (imageId == null || imageId.equals("")){
//根据设计好的API,imageId为空时为查找全部图片信息
try {
selectAll(req,resp);//(调用下面的查找所有的方法)
} catch (SQLException e) {
throw new RuntimeException(e);
}
}else {
try {
selectOneId(imageId,resp);//(调用下面的查找一个图片的方法)
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
private void selectAll(HttpServletRequest req ,HttpServletResponse resp) throws SQLException, IOException {
//1.创建Image对象并查找数据库(查找数据库需要ImageDao类中的selectAll()方法,所以需要先创建imageDao对象)
ImageDao imageDao =new ImageDao();
List<Image> images = imageDao.selectAll();
//2.将gson数组转成Json字符串
//(1)创建一个gson对象
Gson gson = new GsonBuilder().create();
//(2)利用gson.toJson方法将gson转换成json格式的字符串
String jsonData = gson.toJson(images) ;
//3.将Json字符串写入返回值resp中
resp.getWriter().write(jsonData);
}
private void selectOneId(String imageId ,HttpServletResponse resp) throws SQLException, IOException {
//1.创建Image对象并查找数据库
ImageDao imageDao = new ImageDao();
Image image = imageDao.selectOneId(Integer.parseInt(imageId));
//2.将gson数组转成Json字符串
//(1)创建一个gson对象
Gson gson = new GsonBuilder().create();
//(2)利用gson.toJson()方法将gson转换成json字符串
String jsonData = gson.toJson(image);
//3.将Json字符串写入返回值resp中
resp.getWriter().write(jsonData);
}
删除图片的方法:DELETE ,所以要重写doDelete方法
删除图片分为以下几步:
1.首先获取要删除的图片的imageId
2.根据获取的imageId在数据库中查找图片属性(包括存储路径等)用到ImageDao类中的selectOneId
方法
3.根据在数据库中查找到的图片的存储路径找到图片文件,并删除用文件删除file.delete();
4.删除数据库中该图片的信息,用到ImageDao类中的deleteOneId方法
从请求中获取图片imageId存储于imageId中
String imageId = req.getParameter("imageId");
判断imageId中是否有数据,若有则说明请求解析成功,没有则返回错误信息,所以此时加入一个if判断
if(imageId == null || imageId.equals("")){
resp.setStatus(200);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"解析请求失败\"}");
return;
实例化ImageDao对象用于调用seleceOneId方法查找图片属性,主要是存储路径,查到的结果放在Image对象image中
ImageDao imageDao = new ImageDao();
Image image = imageDao.selectOneId(Integer.parseInt(imageId));
处理异常try/catch
此时若image属性为空则说明数据库中没有这个图片,返回一个错误原因
//若imageI的值为空或者imageId字符串等于空字符串,则返回一个错误信息
if(imageId == null || imageId.equals("")){
resp.setStatus(200);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"解析请求失败\"}");
return;
}
首先要根据数据库中存储的图片的存储路径找到图片并删除
File file = new File(image.getPath());
file.deleat();
调用ImageDao类中的deleteOneId方法来删除数据库中的图片属性信息(参数为imageId,类型不同强转一下)
imageDao.deleteOneId(Integer.parseInt(imageId));
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取图片ID
String imageId = req.getParameter("imageId");
resp.setContentType("application/json;charset=utf-8");
//若imageI的值为空或者imageId字符串等于空字符串,则返回一个错误信息
if(imageId == null || imageId.equals("")){
resp.setStatus(200);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"解析请求失败\"}");
return;
}
//2.创建ImageDao对象,根据图片ID在数据库中查找到他的路径
ImageDao imageDao = new ImageDao();
try {
Image image = imageDao.selectOneId(Integer.parseInt(imageId));
if (image == null){
//若image为空则说明URL中读到的imageId在数据库中没有没有,所以image中没有结果
resp.setStatus(200);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"没有这张图片,不能删除\"}");
}
//3.删除数据库中的图片信息
imageDao.deleteOneId(Integer.parseInt(imageId));
//4.删除磁盘中的图片信息
File file = new File(image.getPath());
file.delete();
resp.setStatus(200);
resp.getWriter().write("{\"ok\":true}");
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (JavaImageServerException e) {
throw new RuntimeException(e);
}
}
根据前面的设计查看图片的路径和上面几个操作路径不相同,所以单独放在一个类里
在api包下面新建ImageShowServlet 类,继承自httpServlet 重写doGet方法
查看图片内容需要以下几步
1.获取被查看图片的Id
2.调用ImageDao中的方法以imagrId为参数,获取图片的属性信息
3.根据获取到的图片存储路径找到图片文件,获取到文件内容以字节流的方式返回给浏览器,同时返回文件类型
从请求中获取imageId的值赋给String类型的imageId变量
String imageId = rep.getparameter("imageId");
在获取到imageId的值之后首先我们要判断它是否为空,为空说明请求解析出错,此时要给浏览器返回一个错误信息
if(imageId == null || imageId.equals("")){
resp.setstatus(200);
resp.setContentType("application/json;charset=utf-8");
resp.getwriter().write("{\"ok\":false,\"reason\":\"解析请求出错\"}");
return;
}
获取图片属性信息需要用到ImageDao中的selectOneId方法,所以要先实例化ImageDao类,调用selectOneId方法,获取的返回值存入Image对象image中
ImageDao imageDao = new ImageDao();
Image image = new Image();
image = imageDao.selectOneId(Integer.parseInt(imageId));
处理异常,使用try/catch
判断获取的image属性是否为空,为空说明属性获取失败(即当前imageId对应的图片在数据库中不存在),返回错误信息
if(image ==null ){
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"查找的imageId不存在\"}");
}
在读取文件内容时由获取文件内容的对象每次读取1024个比特的字符放在缓冲区,然后响应的输出流的对象读取缓冲区中的数据作为响应,直到获取文件内容的对象将文件内容读取结束(标志:读取到-1)时停止读取,浏览器按照图片的类型对独到的图片内容进行解析
所以:
(1)首先浏览器读取图片时需要知道要读取的的图片的类型
(2)其次我们还需要有一个FileInputStream对象来获取文件的内容
(3)然后要有一个获取响应输出流的对象outputStream
(4)最后我们还需要一个1024比特大小的缓冲区
(5)操作完成后记得关闭连接
resp.setContentType(image.getContentType());
//将文件类型传给浏览器
File file = new File(image.getPath());
//根据文件位置找到文件,并将其作为file对象
OutputStream outputStream = resp.getOutputStream();
//实例化响应的输出流对象,用来获取缓冲区中的文件内容
FileInputStream fileInputStream = new FileInputStream(file);
//实例化FileInputStream对象fileInputStream,用来读取文件内容
byte[] bytes = new byte[1024];
//创建一个1024byte大小的byte数组bytes用来作为放置获取到的文件内容
while(true){
int len = fileInputStream.read(bytes);
//使用FileInputStream对象的read()方法读取文件内容,并将其存储到字节数组bytes中
//read() 方法的返回值是实际读取到的字节数,若读取到文件末尾则返回值为-1
if (len == -1) {
//读取结束
break;
}
outputStream.write(bytes);
//将FileInputStream对象放入到bytes缓冲区中的文件内容写入响应的输出流对象outputStream中
}
fileInputStream.close();
outputStream.close();
package api;
import dao.Image;
import dao.ImageDao;
import org.apache.commons.fileupload.FileItemFactory;
import sun.awt.image.ImageDecoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.HashSet;
//解析图片
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json;charset=utf-8");
//1.获取ImageId
String imageId = req.getParameter("imageId");
if (imageId == null || imageId.equals("")) {
resp.setStatus(200);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"imageId解析失败\"}");
return;
}
//2.根据imageId查找数据库,图片类型和图片路径
ImageDao imageDao = new ImageDao();
Image image = new Image();
try {
image = imageDao.selectOneId(Integer.parseInt(imageId));
//3.将查找出来的图片类型和图片内容(图片路径得出)返回给浏览器,图片内容(字节流)
if(image ==null ){
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write("{\"ok\":false ,\"reason\":\"查找的imageId不存在\"}");
}
resp.setContentType(image.getContentType());
File file = new File(image.getPath());
OutputStream outputStream = resp.getOutputStream();
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[1024];
while(true){
int len = fileInputStream.read(bytes);
if (len == -1) {
//读取结束
break;
}
outputStream.write(bytes);
}
fileInputStream.close();
outputStream.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
在WEB.xml文件中将类和URL绑定
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>ImageServletservlet-name>
<servlet-class>api.ImageServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>ImageServletservlet-name>
<url-pattern>/imageurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>ImageShowServletservlet-name>
<servlet-class>api.ImageShowServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>ImageShowServletservlet-name>
<url-pattern>/imageShowurl-pattern>
servlet-mapping>
<servlet>
web-app>