图片服务器及测试报告

图片服务器项目

1.项目需求

1.1项目描述:

主要分为三大模块,上传模块,删除模块,展示模块。其中展示模块又可分为展示多张图片与放大图片。进入页面之后就可进行上传操作、删除操作。

1.2核心功能:

本项目主要分为两部分,数据存储部分与服务器模块,使用MySQL数据库存储图片属性,将图片内容保存在本次磁盘,服务器提供上传图片,获取图片属性,根据图片URL获取图片内容和删除图片等接口。
在这里插入图片描述

1.3重要知识点

  1. 简单的Web服务器设计开发能力(Servlet 的使用)
  2. 使用数据库(MySQL)JDBC 操作 MySQL
  3. 数据库设计(根据实际场景设计数据库表结构)
  4. 前后端交互的 API 的设计(基于HTTP协议)
  5. 认识 JSON 数据格式,学习使用 Java 中的 Gson 这个库操作 JSON 数据
  6. 强化 HTTP 协议的理解,学习测试 HTTP 服务器,Postman 工具的使用
  7. 基于 md5 进行校验
  8. 使用 HTML CSS JavaScript 技术构建一个简单的网页

2.项目实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码展示:

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;

/**
 * Create with IntelliJ IDEA
 *
 * @author cyd
 * @date 2021/09/26/10:12
 * @Description:
 */
public class DBUtil {
    private static final String URL="jdbc:mysql://127.0.0.1:3306/image_server";
    private static final String USERNAME="root";
    private static final String PASSWORD="1231";

    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 exc) {
            exc.printStackTrace();
        }
        return null;
    }

    public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
        try {
            if(resultSet!=null){
                resultSet.close();
            }
            if(preparedStatement!=null){
                preparedStatement.close();
            }
            if(connection!=null){
                connection.close();
            }
        } catch (SQLException exc) {
            exc.printStackTrace();
        }
    }

}

Image.java

package dao;

/**
 * Create with IntelliJ IDEA
 *
 * @author cyd
 * @date 2021/09/26/15:22
 * @Description:图片属性
 */
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;

/**
 * Create with IntelliJ IDEA
 *
 * @author cyd
 * @date 2021/09/26/15:22
 * @Description:对数据库进行插入删除查询操作
 */
public class ImageDao {

    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 exc) {
            exc.printStackTrace();
        } catch (JavaImageServerException e) {
            e.printStackTrace();
        }finally {
            //4.关闭连接和statement对象
            DBUtil.close(connection,statement,null);
        }
    }


    public List<Image> selectAll(){
        List<Image> images=new ArrayList<Image>();
        //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 exc) {
            exc.printStackTrace();
        }finally {
            //5.关闭连接
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }


    public Image selectOne(int imageId){
        //1.获取数据库连接
        Connection connection=DBUtil.getConnection();
        //2.构造sql语句
        String sql="select * from image_table where imageId = ? ";
        //3.执行sql语句
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            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 exc) {
            exc.printStackTrace();
        }finally {
            //5.关闭连接
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }


    public void delete(int imageId){
        //1.获取数据库连接
        Connection connection=DBUtil.getConnection();
        //2.拼装sql语句
        String sql="delete from image_table where imageId=?";
        //3.执行sql语句
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            statement=connection.prepareStatement(sql);
            statement.setInt(1,imageId);
            int ret=statement.executeUpdate();
            if(ret!=1){
                throw new JavaImageServerException("删除图片失败!");
            }

        } catch (SQLException exc) {
            exc.printStackTrace();
        } catch (JavaImageServerException e) {
            e.printStackTrace();
        } finally {
            //4.关闭连接
            DBUtil.close(connection,statement,resultSet);

        }
    }


    public Image selectByMd5(String md5){
        //1.获取数据库连接
        Connection connection=DBUtil.getConnection();
        //2.构造sql语句
        String sql="select * from image_table where md5 = ? ";
        //3.执行sql语句
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            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 exc) {
            exc.printStackTrace();
        }finally {
            //5.关闭连接
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

}

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.annotation.WebServlet;
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;
import java.util.SimpleTimeZone;

/**
 * Create with IntelliJ IDEA
 *
 * @author cyd
 * @date 2021/09/27/18:53
 * @Description:
 */
@WebServlet("/image")
public class ImageServlet extends HttpServlet{
    /**
     * 查看图片属性:既能查看所有,也能查看指定
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String imageId=req.getParameter("imageId");
        if(imageId==null||imageId.equals("")){
            selectAll(req,resp);
        }else{
            selectOne(imageId,resp);
        }
    }

    private void selectOne(String imageId, HttpServletResponse resp) throws IOException {

        resp.setContentType("application/json; charset=utf-8");
        ImageDao imageDao=new ImageDao();
        Image image=imageDao.selectOne(Integer.parseInt(imageId));

        Gson gson=new GsonBuilder().create();
        String jsonData=gson.toJson(image);
        resp.getWriter().write(jsonData);

    }

    private void selectAll(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("application/json; charset=utf-8");
        ImageDao imageDao=new ImageDao();
        List<Image> images=imageDao.selectAll();

        Gson gson=new GsonBuilder().create();

        String jsonData=gson.toJson(images);
        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.固定格式
        FileItemFactory factory=new DiskFileItemFactory();
        ServletFileUpload upload=new ServletFileUpload(factory);
            //b.通过upload对象进一步解析请求(解析HTTP请求中奇怪的body中的内容)
                //FileItem代表一个上传文件的对象
        List<FileItem> items=null;
        try {
            //理论上来说,http支持一个请求同时上传多个文件
            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());

        //手动获取当前时间,并格式化日期,yyyyMMdd
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyyMMdd");
        image.setUploadTime(simpleDateFormat.format(new Date()));
        image.setContentType(fileItem.getContentType());

        image.setMd5(DigestUtils.md5Hex(fileItem.get()));
        //自己构造一个路径来保存
        image.setPath("./image/"+image.getMd5());

        ImageDao imageDao=new ImageDao();

        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){
            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}");

    }
}

ImageShow.java

package api;

import dao.Image;
import dao.ImageDao;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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;


/**
 * Create with IntelliJ IDEA
 *
 * @author cyd
 * @date 2021/10/08/17:11
 * @Description:
 */
@WebServlet("/imageShow")
public class ImageShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //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中
            outputStream.write(buffer);
        }
        fileInputStream.close();
        outputStream.close();
    }
}

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>CY 图片列表</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">

        <h2 class="am-hide-sm-only">CY 图片列表</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 style="height: 41px" type="submit" class="am-form-field am-input-sm" value="上传文件">
        </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-sucess">删除</button>
          </div>-->
          <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>Introduction</h3>
            <p class="am-text-sm"> This is a webpage developed by cyd, where you can upload your favorite pictures freely</p>
        </div>

        <div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
            <h3>Social account</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>There are still many areas to be improved on this website, please be patient</p>
        </div>
        <div class="am-u-sm-12 am-u-md-4- am-u-lg-4">
              <h1>We are towards the light</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:{
            images:[
                
            ]
    },
        methods:{
            //GET /image
            getImages(){
                $.ajax({
                    url:"image",
                    type:"get",
                    context:this,
                    success: function(data,status){
                        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();


    /*var app=new Vue({
        el: '#app',
        data:{
            author:"cyd",
            images:[
                {imageId:1,
                imageName:"miao.jpg",
                contentType:"image/jpeg",
                md5:"aabbccdd",
                },
                {imageId:7,
                    imageName:"coolyun.jpg",
                    contentType:"image/jpeg",
                    md5:"aabbccdd",
                },
                {imageId:8,
                    imageName:"lm.jpg",
                    contentType:"image/jpeg",
                    md5:"aabbccdd",
                },
            ]
        }
    })*/

</script>
</body>
</html>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
-->
<!-- $Id: pom.xml 642118 2008-03-28 08:04:16Z reinhard $ -->
<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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <packaging>war</packaging>

  <name>picture_Server</name>
  <groupId>org.example</groupId>
  <artifactId>picture_Server</artifactId>
  <version>1.0-SNAPSHOT</version>

  <build>
    <plugins>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.7</version>
        <configuration>
          <connectors>
            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
              <port>8888</port>
              <maxIdleTime>30000</maxIdleTime>
            </connector>
          </connectors>
          <webAppSourceDirectory>${project.build.directory}/${pom.artifactId}-${pom.version}</webAppSourceDirectory>
          <contextPath>/</contextPath>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <!--dependency>
      <groupId>org.example</groupId>
      <artifactId>[the artifact id of the block to be mounted]</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.49</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>

    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.8.5</version>
    </dependency>

    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.10</version>
    </dependency>

    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

</project>

3.界面展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

项目测试

1.单元测试

框架:junit框架

测试方法:白盒测试,主要对代码的路径覆盖、错误处理等进行测试。

步骤:

1.添加junit依赖

在这里插入图片描述

2.创建测试类

在这里插入图片描述

package dao;

import java.util.List;

import static org.junit.Assert.*;

public class ImageDaoTest {

    @org.junit.Test
    public void insert() {
        ImageDao imageDao=new ImageDao();
        Image image=new Image();

        image.setSize(195083);
        image.setUploadTime("20211014");
        image.setContentType("image/jpeg");
        image.setMd5("8a5a0eb24dd33c14f12e58fcae53d7f5");
        image.setImageName("test.jpg");
        image.setImageId(37);
        image.setPath("./image/8a5a0eb24dd33c14f12e58fcae53d7f5");

        imageDao.insert(image);
    }

    @org.junit.Test
    public void selectAll() {
        ImageDao imageDao = new ImageDao();
        List<Image> lists = imageDao.selectAll();
        System.out.println(lists.size());
        System.out.println();
        for (Image image:lists) {
            System.out.println("imageId = " + image.getImageId()+" "+"imageName = "+image.getImageName());
        }
    }

    @org.junit.Test
    public void selectOne() {
        ImageDao imageDao = new ImageDao();
        try {
            Image image = imageDao.selectOne(2);

            System.out.println(image.getImageName());
            System.out.println(image.getImageId());
            System.out.println(image.getSize());
            System.out.println(image.getMd5());
        }catch (Exception e){
            System.out.println("查询失败,imageId 不存在!!!");
        }
    }

    @org.junit.Test
    public void delete() {
        ImageDao imageDao = new ImageDao();
        List<Image> lists1 = imageDao.selectAll();
        System.out.println("删除前图片容量" + lists1.size());
        imageDao.delete(54);
        List<Image> lists2 = imageDao.selectAll();
        System.out.println("删除后图片容量" + lists2.size());
        if(lists1.size()>lists2.size()) {
            System.out.println("删除成功");
        }else {
            System.out.println("删除失败,imageId 不存在!!!");
        }
    }

    @org.junit.Test
    public void selectByMd5() {
        ImageDao imageDao = new ImageDao();
        try {
            Image image = imageDao.selectByMd5("fbab242a577efdf0c530a27a92e0c255");
            System.out.println(image.getImageId());
            System.out.println(image.getImageName());
            System.out.println(image.getPath());
        } catch (Exception e) {
            System.out.println("查询失败,Md5 不存在!!!");
        }
    }
}

2.系统功能测试

编写测试用例

黑盒测试

在这里插入图片描述

3.自动化测试

编写自动化测试脚本,测试上传,删除功能

unit框架

from selenium import webdriver
import unittest
import time

class imageTest(unittest.TestCase):
    def setUp(self):
        self.driver=webdriver.Chrome(executable_path=r"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe")
        self.driver.get("http://localhost:8080/picture_Server/index.html")
        self.driver.maximize_window()

    def tearDown(self):
        self.driver.quit()

    def test_upload(self):
        driver=self.driver
        driver.find_element_by_name("upload").send_keys("C:/Users/Administrator/Pictures/背景/yy.jpg")
        driver.find_element_by_xpath("/html/body/nav/div/form/div[2]/input").click()
        time.sleep(6)

    @unittest.skip("skipping")
    def test_delete(self):
        driver=self.driver
        driver.find_element_by_xpath("/html/body/div[1]/figure/div/div[6]/button").click()
        time.sleep(6)
        alert=driver.switch_to.alert
        alert.accept()
        time.sleep(6)

    if __name__ == '__main__':
        unittest.main()

4.性能测试

使用loadRunner进行性能测试

录制脚本(上传图片功能)
在这里插入图片描述
请添加图片描述
请添加图片描述
进行测试(设置3个用户并发,每5s退出一个)
请添加图片描述

生成测试报告

我们以测试场景“上传图片”为例,对测试报告进行说明

1.测试说明

功能上传图片
测试目的进行上传图片操作,评估服务器承受能力
场景说明打开首页,点击登录,选择照片,点击上传
事务说明上传图片
参数设置通过HP LoadRunner11.00压力测试工具,导入录制脚本,设置参数如下: Start vusers:50,100Vusers every 00:00:05 Duration:Run 3 minute Stop vusers:50Vusers every 00:00:05 All user:50

2.结果分析

指标最大平均
并发用户数50
响应时间上传15.2s4.18s
关闭上传10.2s2.3s
点击率259117

1.统计信息摘要

下图说明本次测试运行的最大并发数为50,总吞吐量为1,740,830,323字节,平均每秒吞吐量为6,376,668字节,总的请求数为32,868,平均每秒的请求为120.396。对于吞吐量,单位时间内吞吐量越大,说明服务器的处理能越好,而请求数仅表示客户端向服务器发出的请求数,与吞吐量一般是成正比关系。
在这里插入图片描述

2.事务摘要

这部分给出了场景执行结束后相关Action的平均响应时间、通过率等情况,如下图所示,从该图中我们可以得到每个Action的平均响应时间与业务成功率。
在这里插入图片描述

在这里插入图片描述

3.HTTP响应摘要

该部分显示在场景执行中,每次发送HTTP请求所得到的状态。本次测试其中“HTTP200”有31,129,000次,基本所有的请求都能成功。
在这里插入图片描述
4.每秒点击数

“Hits per Second(每秒点击数)”反映了每秒向服务器提交的请求数量。下图显示的是“Hits per Second”与“Throughput”的复合图。如果两种图像的曲线都正常且基本一致,说明服务器能及时接受客户端的请求,并能返回结果。从图中可以看出,整体表现一般。
在这里插入图片描述

5.业务成功率

业务成功率就是事务成功率,用户一般把一个Action当做一笔业务,在“Transaction Summary”中我们可以很明确地看到每个事务的执行状态
在这里插入图片描述

5.项目bug

1.删除图片后刷新页面图片依旧存在
原因:删除图片未删除干净(上传时本地还有一份图片数据,删除时未删除)

2.上传已删除过的图片显示写失败,再次刷新页面才会显图片
原因:删除图片未删除干净(上传时本地还有一份图片数据,删除时未删除)

3.上传非图片的文件上传成功
建议:上传时进行判断

4.上传空文件上传成功
建议:上传时进行判断

5.全部图片在同一个页面,图片过多时,对服务器压力过大
原因:未分页

6.图片名称过长时未折行展示,影响美观
建议:折行展示

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值