图片服务器项目:
网盘百度链接:https://pan.baidu.com/s/1YIGnhy6QxoLBzf4CGjtM2A
提取码:1111
项目分析+代码
1、项目分析
过程分析:请求:浏览器—>网络—>Tomcat—>本地代码—>数据库
响应:数据库—>本地代码—>Tomcat—>网络—>浏览器
2、代码展示
ImageServlet.java
package api;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import dao.Image;
import dao.ImageDao;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
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.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class ImageServlet extends HttpServlet {
/**
* 查看图片属性: 既能查看所有, 也能查看指定
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 考虑到查看所有图片属性和查看指定图片属性
// 通过是否 URL 中带有 imageId 参数来进行区分.
// 存在 imageId 查看指定图片属性, 否则就查看所有图片属性
// 例如: URL /image?imageId=100
// imageId 的值就是 "100"
// 如果 URL 中不存在 imageId 那么返回 null
String imageId = req.getParameter("imageId");
if (imageId == null || imageId.equals("")) {
// 查看所有图片属性
selectAll(req, resp);
} else {
// 查看指定图片
selectOne(imageId, resp);
}
}
private void selectAll(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("application/json; charset=utf-8");
// 1. 创建一个 ImageDao 对象, 并查找数据库
ImageDao imageDao = new ImageDao();
List<Image> images = imageDao.selectAll();
// 2. 把查找到的结果转成 JSON 格式的字符串, 并且写回给 resp 对象
Gson gson = new GsonBuilder().create();
// jsonData 就是一个 json 格式的字符串了, 就和之前约定的格式是一样的了.
// 重点体会下面这行代码, 这个方法的核心, gson 帮我们自动完成了大量的格式转换工作
// 只要把之前的相关的字段都约定成统一的命名, 下面的操作就可以一步到位的完成整个转换
String jsonData = gson.toJson(images);
resp.getWriter().write(jsonData);
}
private void selectOne(String imageId, HttpServletResponse resp) throws IOException {
resp.setContentType("application/json; charset=utf-8");
// 1. 创建 ImageDao 对象
ImageDao imageDao = new ImageDao();
Image image = imageDao.selectOne(Integer.parseInt(imageId));
// 2. 使用 gson 把查到的数据转成 json 格式, 并写回给响应对象
Gson gson = new GsonBuilder().create();
String jsonData = gson.toJson(image);
resp.getWriter().write(jsonData);
}
/**
* 上传图片
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取图片的属性信息, 并且存入数据库
// a) 需要创建一个 factory 对象 和 upload 对象, 这是为了获取到图片属性做的准备工作
// 固定的逻辑
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// b) 通过 upload 对象进一步解析请求(解析HTTP请求中的 body 中的内容)
// FileItem 就代表一个上传的文件对象.
// 理论上来说, HTTP 支持一个请求中同时上传多个文件
List<FileItem> items = null;
try {
items = upload.parseRequest(req);
} catch (FileUploadException e) {
// 出现异常说明解析出错!
e.printStackTrace();
// 告诉客户端出现的具体的错误是啥
resp.setContentType("application/json; charset=utf-8");
resp.getWriter().write("{ \"ok\": false, \"reason\": \"请求解析失败\" }");
return;
}
// c) 把 FileItem 中的属性提取出来, 转换成 Image 对象, 才能存到数据库中
// 当前只考虑一张图片的情况
FileItem fileItem = items.get(0);
Image image = new Image();
image.setImageName(fileItem.getName());
image.setSize((int)fileItem.getSize());
// 手动获取一下当前日期, 并转成格式化日期, yyMMdd => 20200218
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
image.setUploadTime(simpleDateFormat.format(new Date()));
image.setContentType(fileItem.getContentType());
// MD5 暂时先不去计算
image.setMd5(DigestUtils.md5Hex(fileItem.get()));
// 自己构造一个路径来保存, 引入时间戳是为了让文件路径能够唯一
image.setPath("./image/" + image.getMd5());
// 存到数据库中
ImageDao imageDao = new ImageDao();
// 看看数据库中是否存在相同的 MD5 值的图片, 不存在, 返回 null
Image existImage = imageDao.selectByMd5(image.getMd5());
imageDao.insert(image);
// 2. 获取图片的内容信息, 并且写入磁盘文件
if (existImage == null) {
File file = new File(image.getPath());
try {
fileItem.write(file);
} catch (Exception e) {
e.printStackTrace();
resp.setContentType("application/json; charset=utf-8");
resp.getWriter().write("{ \"ok\": false, \"reason\": \"写磁盘失败\" }");
return;
}
}
// 3. 给客户端返回一个结果数据
// resp.setContentType("application/json; charset=utf-8");
// resp.getWriter().write("{ \"ok\": true }");
resp.sendRedirect("index.html");
}
/**
* 删除指定图片
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doDelete(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.getWriter().write("{ \"ok\": false, \"reason\": \"解析请求失败\" }");
return;
}
// 2. 创建 ImageDao 对象, 查看到该图片对象对应的相关属性(这是为了知道这个图片对应的文件路径)
ImageDao imageDao = new ImageDao();
Image image = imageDao.selectOne(Integer.parseInt(imageId));
if (image == null) {
// 此时请求中传入的 id 在数据库中不存在.
resp.setStatus(200);
resp.getWriter().write("{ \"ok\": false, \"reason\": \"imageId 在数据库中不存在\" }");
return;
}
// 3. 删除数据库中的记录
imageDao.delete(Integer.parseInt(imageId));
// 4. 删除本地磁盘文件
File file = new File(image.getPath());
file.delete();
resp.setStatus(200);
resp.getWriter().write("{ \"ok\": true }");
}
}
ImageShowServlet.java
package api;
import dao.Image;
import dao.ImageDao;
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.util.HashSet;
public class ImageShowServlet extends HttpServlet {
static private HashSet<String> whiteList = new HashSet<>();
static {
whiteList.add("http://47.98.116.42:8080/java_image_server/index.html");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String referer = req.getHeader("Referer");
if (!whiteList.contains(referer)) {
resp.setContentType("application/json; charset: utf-8");
resp.getWriter().write("{ \"ok\": false, \"reason\": \"未授权的访问\" }");
return;
}
// 1. 解析出 imageId
String imageId = req.getParameter("imageId");
if (imageId == null || imageId.equals("")) {
resp.setContentType("application/json; charset: utf-8");
resp.getWriter().write("{ \"ok\": false, \"reason\": \"imageId 解析失败\" }");
return;
}
// 2. 根据 imageId 查找数据库, 得到对应的图片属性信息(需要知道图片存储的路径)
ImageDao imageDao = new ImageDao();
Image image = imageDao.selectOne(Integer.parseInt(imageId));
// 3. 根据路径打开文件, 读取其中的内容, 写入到响应对象中
resp.setContentType(image.getContentType());
File file = new File(image.getPath());
// 由于图片是二进制文件, 应该使用字节流的方式读取文件
OutputStream outputStream = resp.getOutputStream();
FileInputStream fileInputStream = new FileInputStream(file);
byte[] buffer = new byte[1024];
while (true) {
int len = fileInputStream.read(buffer);
if (len == -1) {
// 文件读取结束
break;
}
// 此时已经读到一部分数据, 放到 buffer 里, 把 buffer 中的内容写到响应对象中
outputStream.write(buffer);
}
fileInputStream.close();
outputStream.close();
}
}
DBUtil.java
package dao;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBUtil {
private static final String URL = "jdbc:mysql://127.0.0.1:3306/java_image_server?characterEncoding=utf8&useSSL=true";
private static final String USERNAME = "root";
private static final String PASSWORD = "";
private static volatile DataSource dataSource = null;
public static DataSource getDataSource() {
// 通过这个方法来创建 DataSource 的实例
if (dataSource == null) {
synchronized (DBUtil.class) {
if (dataSource == null) {
dataSource = new MysqlDataSource();
MysqlDataSource tmpDataSource = (MysqlDataSource) dataSource;
tmpDataSource.setURL(URL);
tmpDataSource.setUser(USERNAME);
tmpDataSource.setPassword(PASSWORD);
}
}
}
return dataSource;
}
public static Connection getConnection() {
try {
return getDataSource().getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Image.java
package dao;
public class Image {
private int imageId;
private String imageName;
private int size;
private String uploadTime;
private String contentType;
private String path;
private String md5;
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getImageName() {
return imageName;
}
public void setImageName(String imageName) {
this.imageName = imageName;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getUploadTime() {
return uploadTime;
}
public void setUploadTime(String uploadTime) {
this.uploadTime = uploadTime;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
@Override
public String toString() {
return "Image{" +
"imageId=" + imageId +
", imageName='" + imageName + '\'' +
", size=" + size +
", uploadTime='" + uploadTime + '\'' +
", contentType='" + contentType + '\'' +
", path='" + path + '\'' +
", md5='" + md5 + '\'' +
'}';
}
}
ImageDao.java
package dao;
import common.JavaImageServerException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ImageDao {
/**
* 把 image 对象插入到数据库中
* @param image
*/
public void insert(Image image) {
// 1. 获取数据库连接
Connection connection = DBUtil.getConnection();
// 2. 创建并拼装 SQL 语句
String sql = "insert into image_table values(null, ?, ?, ?, ?, ?, ?)";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1, image.getImageName());
statement.setInt(2, image.getSize());
statement.setString(3, image.getUploadTime());
statement.setString(4, image.getContentType());
statement.setString(5, image.getPath());
statement.setString(6, image.getMd5());
// 3. 执行 SQL 语句
int ret = statement.executeUpdate();
if (ret != 1) {
// 程序出现问题, 抛出一个异常
throw new JavaImageServerException("插入数据库出错!");
}
} catch (SQLException | JavaImageServerException e) {
e.printStackTrace();
} finally {
// 4. 关闭连接和statement对象
DBUtil.close(connection, statement, null);
}
}
/**
* 查找数据库中的所有图片的信息
* @return
*/
public List<Image> selectAll() {
List<Image> images = new ArrayList<>();
// 1. 获取数据库连接
Connection connection = DBUtil.getConnection();
// 2. 构造 SQL 语句
String sql = "select * from image_table";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 3. 执行 SQL 语句
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
// 4. 处理结果集
while (resultSet.next()) {
Image image = new Image();
image.setImageId(resultSet.getInt("imageId"));
image.setImageName(resultSet.getString("imageName"));
image.setSize(resultSet.getInt("size"));
image.setUploadTime(resultSet.getString("uploadTime"));
image.setContentType(resultSet.getString("contentType"));
image.setPath(resultSet.getString("path"));
image.setMd5(resultSet.getString("md5"));
images.add(image);
}
return images;
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 5. 关闭连接
DBUtil.close(connection, statement, resultSet);
}
return null;
}
/**
* 根据 imageId 查找指定的图片信息
* @param imageId
* @return
*/
public Image selectOne(int imageId) {
// 1. 获取数据库连接
Connection connection = DBUtil.getConnection();
// 2. 构造 SQL 语句
String sql = "select * from image_table where imageId = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 3. 执行 SQL 语句
statement = connection.prepareStatement(sql);
statement.setInt(1, imageId);
resultSet = statement.executeQuery();
// 4. 处理结果集
if (resultSet.next()) {
Image image = new Image();
image.setImageId(resultSet.getInt("imageId"));
image.setImageName(resultSet.getString("imageName"));
image.setSize(resultSet.getInt("size"));
image.setUploadTime(resultSet.getString("uploadTime"));
image.setContentType(resultSet.getString("contentType"));
image.setPath(resultSet.getString("path"));
image.setMd5(resultSet.getString("md5"));
return image;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 5. 关闭链接
DBUtil.close(connection, statement, resultSet);
}
return null;
}
/**
* 根据 imageId 删除指定的图片
* @param imageId
*/
public void delete(int imageId) {
// 1. 获取数据库连接
Connection connection = DBUtil.getConnection();
// 2. 拼装 SQL 语句
String sql = "delete from image_table where imageId = ?";
PreparedStatement statement = null;
// 3. 执行 SQL 语句
try {
statement = connection.prepareStatement(sql);
statement.setInt(1, imageId);
int ret = statement.executeUpdate();
if (ret != 1) {
throw new JavaImageServerException("删除数据库操作失败");
}
} catch (SQLException | JavaImageServerException e) {
e.printStackTrace();
} finally {
// 4. 关闭连接
DBUtil.close(connection, statement, null);
}
}
// 由于汤老湿的数据库是在阿里云服务器上, 不在本地. 这个程序在本地直接运行无法访问数据库
// 此处我需要把这个程序部署到云服务器上执行才能看到效果
// 打一个 jar 包, 把 jar 包拷贝到云服务器上, 就可以执行了
public static void main(String[] args) {
// 用于进行简单的测试
// 1. 测试插入数据
// Image image = new Image();
// image.setImageName("1.png");
// image.setSize(100);
// image.setUploadTime("20200216");
// image.setContentType("image/png");
// image.setPath("./data/1.png");
// image.setMd5("11223344");
// ImageDao imageDao = new ImageDao();
// imageDao.insert(image);
// 2. 测试查找所有图片信息
// ImageDao imageDao = new ImageDao();
// List<Image> images = imageDao.selectAll();
// System.out.println(images);
// 3. 测试查找指定图片信息
// ImageDao imageDao = new ImageDao();
// Image image = imageDao.selectOne(1);
// System.out.println(image);
// 4. 测试删除图片
ImageDao imageDao = new ImageDao();
imageDao.delete(1);
}
public Image selectByMd5(String md5) {
// 1. 获取数据库连接
Connection connection = DBUtil.getConnection();
// 2. 构造 SQL 语句
String sql = "select * from image_table where md5 = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 3. 执行 SQL 语句
statement = connection.prepareStatement(sql);
statement.setString(1, md5);
resultSet = statement.executeQuery();
// 4. 处理结果集
if (resultSet.next()) {
Image image = new Image();
image.setImageId(resultSet.getInt("imageId"));
image.setImageName(resultSet.getString("imageName"));
image.setSize(resultSet.getInt("size"));
image.setUploadTime(resultSet.getString("uploadTime"));
image.setContentType(resultSet.getString("contentType"));
image.setPath(resultSet.getString("path"));
image.setMd5(resultSet.getString("md5"));
return image;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 5. 关闭链接
DBUtil.close(connection, statement, resultSet);
}
return null;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>api.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/image</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ImageShowServlet</servlet-name>
<servlet-class>api.ImageShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageShowServlet</servlet-name>
<url-pattern>/imageShow</url-pattern>
</servlet-mapping>
</web-app>
index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>小猿的相册程序</title>
<meta name="renderer" content="webkit">
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<link rel="icon" type="image/png" href="assets/i/favicon.png">
<meta name="mobile-web-app-capable" content="yes">
<link rel="icon" sizes="192x192" href="assets/i/app-icon72x72@2x.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Amaze UI"/>
<link rel="apple-touch-icon-precomposed" href="assets/i/app-icon72x72@2x.png">
<meta name="msapplication-TileImage" content="assets/i/app-icon72x72@2x.png">
<meta name="msapplication-TileColor" content="#0e90d2">
<link rel="stylesheet" href="assets/css/amazeui.min.css">
<link rel="stylesheet" href="assets/css/app.css">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body id="blog-article-sidebar">
<!-- header start -->
<header class="am-g am-g-fixed blog-fixed blog-text-center blog-header">
<div class="am-u-sm-8 am-u-sm-centered">
<img width="200" src="http://47.98.116.42:8080/java_image_server/imageShow?imageId=10" alt="Amaze UI Logo"/>
<h2 class="am-hide-sm-only">小猿的相册程序</h2>
</div>
</header>
<!-- header end -->
<hr>
<!-- nav start -->
<nav class="am-g am-g-fixed blog-fixed blog-nav">
<button class="am-topbar-btn am-topbar-toggle am-btn am-btn-sm am-btn-success am-show-sm-only blog-button" data-am-collapse="{target: '#blog-collapse'}" ><span class="am-sr-only">导航切换</span> <span class="am-icon-bars"></span></button>
<div class="am-collapse am-topbar-collapse" id="blog-collapse">
<ul class="am-nav am-nav-pills am-topbar-nav">
</ul>
<form class="am-topbar-form am-topbar-right am-form-inline" method="POST"
action="image" enctype="multipart/form-data">
<div class="am-form-group">
<input type="file" class="am-form-field am-input-sm" id="upload" name="upload">
</div>
<div class="am-form-group">
<input type="submit" class="am-form-field am-input-sm" style="height:41px">
</div>
</form>
</div>
</nav>
<!-- nav end -->
<hr>
<!-- content srart -->
<div class="am-g am-g-fixed blog-fixed blog-content" id="app">
<figure data-am-widget="figure" class="am am-figure am-figure-default " data-am-figure="{ pureview: 'true' }">
<div id="container">
<div v-for="image in images">
<img style="width:200px; height: 200px" v-bind:src="'imageShow?imageId=' + image.imageId">
<h3>{{image.imageName}}</h3>
<button style="width:100%" v-on:click.stop="remove(image.imageId)" class="am-btn am-btn-success">删除</button>
</div>
</div>
</figure>
</div>
<!-- content end -->
<footer class="blog-footer">
<div class="am-g am-g-fixed blog-fixed am-u-sm-centered blog-footer-padding">
<div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
<h3>模板简介</h3>
<p class="am-text-sm">这是一个使用amazeUI做的简单的前端模板。<br> 博客/ 资讯类 前端模板 <br> 支持响应式,多种布局,包括主页、文章页、媒体页、分类页等<br>嗯嗯嗯,不知道说啥了。外面的世界真精彩<br><br>
Amaze UI 使用 MIT 许可证发布,用户可以自由使用、复制、修改、合并、出版发行、散布、再授权及贩售 Amaze UI 及其副本。</p>
</div>
<div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
<h3>社交账号</h3>
<p>
<a href=""><span class="am-icon-qq am-icon-fw am-primary blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-github am-icon-fw blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-weibo am-icon-fw blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-reddit am-icon-fw blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-weixin am-icon-fw blog-icon blog-icon"></span></a>
</p>
<h3>Credits</h3>
<p>我们追求卓越,然时间、经验、能力有限。Amaze UI 有很多不足的地方,希望大家包容、不吝赐教,给我们提意见、建议。感谢你们!</p>
</div>
<div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
<h1>我们站在巨人的肩膀上</h1>
<h3>Heroes</h3>
<p>
<ul>
<li>jQuery</li>
<li>Zepto.js</li>
<li>Seajs</li>
<li>LESS</li>
<li>...</li>
</ul>
</p>
</div>
</div>
<div class="blog-text-center">© 2015 AllMobilize, Inc. Licensed under MIT license. Made with love By LWXYFER</div>
</footer>
<!--[if (gte IE 9)|!(IE)]><!-->
<script src="assets/js/jquery.min.js"></script>
<!--<![endif]-->
<!--[if lte IE 8 ]>
<script src="http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<script src="http://cdn.staticfile.org/modernizr/2.8.3/modernizr.js"></script>
<script src="assets/js/amazeui.ie8polyfill.min.js"></script>
<![endif]-->
<script src="assets/js/amazeui.min.js"></script>
<script src="assets/js/pinto.min.js"></script>
<script src="assets/js/img.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
author: "小猿",
images: [
]
},
methods: {
// GET /image
getImages() {
$.ajax({
url: "image",
type: "get",
context: this,
success: function(data, status) {
// 此处的代码在浏览器收到响应之后, 才会执行到
// 参数中的 data 这就相当于收到的 HTTP 响应中的 body 部分
this.images = data;
$('#app').resize();
}
})
},
remove(imageId) {
$.ajax({
url: "image?imageId=" + imageId,
type: "delete",
context: this,
success: function(data, status) {
this.getImages();
// 弹出对话框
alert("删除成功!");
}
})
}
}
})
app.getImages();
</script>
</body>
</html>
index.html
<html>
<head>
</head>
<body>
<form id="upload-form" action="image" method="post" enctype="multipart/form-data" >
<input type="file" id="upload" name="upload" /> <br />
<input type="submit" value="Upload" />
</form>
</body>
</html>
lw-img.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>image | Amaze UI Examples</title>
<meta name="renderer" content="webkit">
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<link rel="icon" type="image/png" href="assets/i/favicon.png">
<meta name="mobile-web-app-capable" content="yes">
<link rel="icon" sizes="192x192" href="assets/i/app-icon72x72@2x.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Amaze UI"/>
<link rel="apple-touch-icon-precomposed" href="assets/i/app-icon72x72@2x.png">
<meta name="msapplication-TileImage" content="assets/i/app-icon72x72@2x.png">
<meta name="msapplication-TileColor" content="#0e90d2">
<link rel="stylesheet" href="assets/css/amazeui.min.css">
<link rel="stylesheet" href="assets/css/app.css">
</head>
<body id="blog-article-sidebar">
<!-- header start -->
<header class="am-g am-g-fixed blog-fixed blog-text-center blog-header">
<div class="am-u-sm-8 am-u-sm-centered">
<img width="200" src="http://s.amazeui.org/media/i/brand/amazeui-b.png" alt="Amaze UI Logo"/>
<h2 class="am-hide-sm-only">中国首个开源 HTML5 跨屏前端框架</h2>
</div>
</header>
<!-- header end -->
<hr>
<!-- nav start -->
<nav class="am-g am-g-fixed blog-fixed blog-nav">
<button class="am-topbar-btn am-topbar-toggle am-btn am-btn-sm am-btn-success am-show-sm-only blog-button" data-am-collapse="{target: '#blog-collapse'}" ><span class="am-sr-only">导航切换</span> <span class="am-icon-bars"></span></button>
<div class="am-collapse am-topbar-collapse" id="blog-collapse">
<ul class="am-nav am-nav-pills am-topbar-nav">
<li class="am-active"><a href="lw-index.html">首页</a></li>
<li class="am-dropdown" data-am-dropdown>
<a class="am-dropdown-toggle" data-am-dropdown-toggle href="javascript:;">
首页布局 <span class="am-icon-caret-down"></span>
</a>
<ul class="am-dropdown-content">
<li><a href="lw-index.html">1. blog-index-standard</a></li>
<li><a href="lw-index-nosidebar.html">2. blog-index-nosidebar</a></li>
<li><a href="lw-index-center.html">3. blog-index-layout</a></li>
<li><a href="lw-index-noslider.html">4. blog-index-noslider</a></li>
</ul>
</li>
<li><a href="lw-article.html">标准文章</a></li>
<li><a href="lw-img.html">图片库</a></li>
<li><a href="lw-article-fullwidth.html">全宽页面</a></li>
<li><a href="lw-timeline.html">存档</a></li>
</ul>
<form class="am-topbar-form am-topbar-right am-form-inline" role="search">
<div class="am-form-group">
<input type="text" class="am-form-field am-input-sm" placeholder="搜索">
</div>
</form>
</div>
</nav>
<!-- nav end -->
<hr>
<!-- content srart -->
<div class="am-g am-g-fixed blog-fixed blog-content">
<figure data-am-widget="figure" class="am am-figure am-figure-default " data-am-figure="{ pureview: 'true' }">
<div id="container">
<div><img src="images/01.jpg"><h3>Agfa</h3></div>
<div><img src="images/02.jpg"><h3>Auto</h3></div>
<div><img src="images/03.jpg"><h3>Bald eagle</h3></div>
<div><img src="images/04.jpg"><h3>Black swan</h3></div>
<div><img src="images/05.jpg"><h3>Book shelf</h3></div>
<div><img src="images/06.jpg"><h3>Camera</h3></div>
<div><img src="images/07.jpg"><h3>Camera</h3></div>
<div><img src="images/25.jpg"><h3>Vintage camera</h3></div>
<div><img src="images/09.jpg"><h3>Coffee</h3></div>
<div><img src="images/10.jpg"><h3>Cookies</h3></div>
<div><img src="images/11.jpg"><h3>Cubes</h3></div>
<div><img src="images/12.jpg"><h3>DJ</h3></div>
<div><img src="images/13.jpg"><h3>Doors</h3></div>
<div><img src="images/14.jpg"><h3>Matchbox</h3></div>
<div><img src="images/15.jpg"><h3>Freiburg</h3></div>
<div><img src="images/16.jpg"><h3>Henna</h3></div>
<div><img src="images/17.jpg"><h3>Home office</h3></div>
<div><img src="images/18.jpg"><h3>iPad</h3></div>
<div><img src="images/19.jpg"><h3>Keyboard</h3></div>
<div><img src="images/20.jpg"><h3>Lynx</h3></div>
<div><img src="images/21.jpg"><h3>Mac</h3></div>
<div><img src="images/22.jpg"><h3>Notebook</h3></div>
<div><img src="images/23.jpg"><h3>Thoughts</h3></div>
<div><img src="images/24.jpg"><h3>Office</h3></div>
<div><img src="images/25.jpg"><h3>Children</h3></div>
<div><img src="images/26.jpg"><h3>Portrait</h3></div>
<div><img src="images/27.jpg"><h3>Startup</h3></div>
<div><img src="images/28.jpg"><h3>Sun</h3></div>
<div><img src="images/29.jpg"><h3>The Eiffel Tower</h3></div>
<div><img src="images/30.jpg"><h3>Water drops</h3></div>
</div>
</figure>
</div>
<!-- content end -->
<footer class="blog-footer">
<div class="am-g am-g-fixed blog-fixed am-u-sm-centered blog-footer-padding">
<div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
<h3>模板简介</h3>
<p class="am-text-sm">这是一个使用amazeUI做的简单的前端模板。<br> 博客/ 资讯类 前端模板 <br> 支持响应式,多种布局,包括主页、文章页、媒体页、分类页等<br>嗯嗯嗯,不知道说啥了。外面的世界真精彩<br><br>
Amaze UI 使用 MIT 许可证发布,用户可以自由使用、复制、修改、合并、出版发行、散布、再授权及贩售 Amaze UI 及其副本。</p>
</div>
<div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
<h3>社交账号</h3>
<p>
<a href=""><span class="am-icon-qq am-icon-fw am-primary blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-github am-icon-fw blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-weibo am-icon-fw blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-reddit am-icon-fw blog-icon blog-icon"></span></a>
<a href=""><span class="am-icon-weixin am-icon-fw blog-icon blog-icon"></span></a>
</p>
<h3>Credits</h3>
<p>我们追求卓越,然时间、经验、能力有限。Amaze UI 有很多不足的地方,希望大家包容、不吝赐教,给我们提意见、建议。感谢你们!</p>
</div>
<div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
<h1>我们站在巨人的肩膀上</h1>
<h3>Heroes</h3>
<p>
<ul>
<li>jQuery</li>
<li>Zepto.js</li>
<li>Seajs</li>
<li>LESS</li>
<li>...</li>
</ul>
</p>
</div>
</div>
<div class="blog-text-center">© 2015 AllMobilize, Inc. Licensed under MIT license. Made with love By LWXYFER</div>
</footer>
<!--[if (gte IE 9)|!(IE)]><!-->
<script src="assets/js/jquery.min.js"></script>
<!--<![endif]-->
<!--[if lte IE 8 ]>
<script src="http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<script src="http://cdn.staticfile.org/modernizr/2.8.3/modernizr.js"></script>
<script src="assets/js/amazeui.ie8polyfill.min.js"></script>
<![endif]-->
<script src="assets/js/amazeui.min.js"></script>
<script src="assets/js/pinto.min.js"></script>
<script src="assets/js/img.js"></script>
</body>
</html>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bit</groupId>
<artifactId>java_image_server</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 打包方式是 war 包,一种用于 web 应用的包,原理类似 jar 包 -->
<packaging>war</packaging>
<!-- 指定属性信息 -->
<properties>
<encoding>UTF-8</encoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- 加入 servlet 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<!-- servlet 版本和 tomcat 版本有对应关系,切记 -->
<version>3.1.0</version>
<!-- 这个意思是我们只在开发阶段需要这个依赖,部署到 tomcat 上时就不需要了 -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<!--JSON库,gson-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
</dependencies>
<build>
<!-- 指定最终 war 包的名称 -->
<finalName>java_image_server</finalName>
<!-- 明确指定一些插件的版本,以免受到 maven 版本的影响 -->
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
图片服务器项目测试: