【Java实战项目】【超详细过程】—— 大饼的图片服务器6

news2024/12/25 12:59:52

目录

  • 前言
  • 一、引入MD5
    • 1.引入md5计算依赖
    • 2.按照md5值查找图片属性
    • 3.存储图片
    • 4.删除图片
  • 二、防盗链
  • 三、分类查看图片
    • 1.思路:
    • 2.数据库
    • 3.Image
    • 4.from表单
    • 5.ImageDao类中原有方法
    • 6.按照类型sort在数据库中查找图片属性
    • 7.ImageServlet 类
    • 8.ImageSortServlet类
    • 9.WEB.xml绑定URL
    • 10.新建.html文件
    • 11.index.html
    • 12.加入白名单

前言

前面我们已经将醒目的主要框架搭建起来了,现在我们主要来解决前面遗留的问题,并且对新加入的功能进行代码编写,例如:md5实现,加入白名单实现防盗功能,按照图片类型查看图片功能


一、引入MD5

我们使用MD5将图片内容的到我们所需要的一串唯一的代表图片内容的特征码
MD5码可以唯一地代表原信息的特征,通常用于密码的加密存储,数字签名,文件完整性验证等。
我们如果想要使用md5来进行存储,那么

1.首先我们存储图片的路径应该变为图片md5值(需要计算md5值,然而计算md5值需要引入依赖)
2.其次为了避免重复存储我们需要在将文件写入磁盘前进行判断,判断该md5值的图片在数据库中是否为空(在图片属性信息存入数据库之前),如果存在不为空该md5值的图片则说明之前已经保存过相同的图片了(相同图片内容对应的md5值相同)无需再次保存
3.判断md5值相同的image是否只有一个需要一个按照md5值查找数据库操作的方法,在ImageDao中加入一个按照Md5值查找数据库的方法
4.因为上述操作会导致数据库中不同图片的路径对应同一个磁盘中的图片,所以再删除时需要注意再次进行判断是否删除磁盘图片(在删除数据库图片信息后与删除磁盘图片前,判断数据库中是否存在该md5值的图片,如果有则不删除,没有则删除)


1.引入md5计算依赖

该代码放在pom.xml中

    <!--md5所需依赖-->
    <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.14</version>
    </dependency>

2.按照md5值查找图片属性

数据库中可能不止一个md5值相同的图片属性信息,所以我们需要返回Image列表,其他和查找全部图片操作相同

    public List<Image> selectMd5(String md5)throws SQLException {
        List<Image> images = new ArrayList<>();//查找所有的结果返回不止一条数据,所以用列表存放结果集
        Connection connection = DBUtil.getConnection();//建立数据库连接
        String SQL= "select * from image where imageId = ?";//构造SQL语言
        PreparedStatement statement = null;//statement 用于拼接SQL语言
        ResultSet resultSet = null;
        try{
            statement = connection.prepareStatement(SQL);//拼接SQL语言
            statement.setString(1,md5);
            //执行SQL
            resultSet = statement.executeQuery();
            //处理结果集
            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"));
                image.setSort(resultSet.getString("sort"));
                images.add(image);
            }
            return images;
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement, resultSet);
        }
        return null;
    }

3.存储图片

1.md5计算:

//md5计算
image.setMd5(DigestUtils.md5Hex(fileItem.get()));

2.图片存储地址更改:(由时间戳存储改为md5存储)

image.setPath("./image/" + image.getMd5());

3.判断图片是否写入磁盘:
在将图片属性信息存入数据库之前先查找该图片的md5值相同的图片有多少,返回一个图片列表
然后判断该列表是否为空,为空则写入磁盘

//调用 imageDao.selectMd5()方法
List<Image> imageServletMd5 = imageDao.selectMd5(image.getMd5());
if (imageServletMd5 == null || imageServletMd5.isEmpty()) {
    //2.将图片内容存入磁盘
    File file = new File(image.getPath());
    System.out.println(file);
    try {
          fileItem.write(file); 
          System.out.println(fileItem);
    } catch (Exception e) {
          resp.setContentType("application/json;charset=utf-8");
          resp.getWriter().write("{\"ok\":false ,\"reason\":\"写入磁盘失败\"}");
    }
}

4.删除图片

删除数据库图片信息后与删除磁盘图片前先确认该数据库中是否还有和该图片Md5值相同的图片,若有泽不删除磁盘图片,无则删除

//3.删除数据库中的图片信息
imageDao.deleteOneId(Integer.parseInt(imageId));
//判断数据库中该image的md5是否有数据,如若有责不删除磁盘,如果没有则删除磁盘数据
List<Image> imageServletMd5 = imageDao.selectMd5(image.getMd5());
if (imageServletMd5 == null || imageServletMd5.isEmpty()){
    //4.删除磁盘中的图片信息
    File file = new File(image.getPath());
    file.delete();
}
resp.setStatus(200);
resp.getWriter().write("{\"ok\":true}");

二、防盗链

实现防盗链可以使用最简单的白名单来设置,在白名单中设置允许调用这个方法(查看图片)的上一跳页面
可以定义一个HashSet< String >集合类型的whiteList,用来存放允许访问的页面的URL
然后在运行查看图片的代码之前判断上一跳的页面的URL是否在白名单里面,在的话就继续执行查看图片的代码,不在则不执行查看图片的代码,而是返回一个:“非法访问”。

public class ImageShowServlet extends HttpServlet {
    static private HashSet<String> whiteList = new HashSet<>();
    //创建一个静态私有HashSet集合类型为String,名为whiteList
    static {
        //在静态块中初始化whiteList这个静态私有HashSet集合
        whiteList.add("http://127.0.0.1:8080/img/index.html");
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf-8");
        String referer = req.getHeader("referer");
        //HttpServletRequest对象的一个方法,从HTTP请求中获取名称为:"referer"的头部信息,并将其存储在字符串变量referer中
        // "referer"头部信息通常包含了发起请求的页面的URL
        if(!whiteList.contains(referer)){
            //检查referer是否在白名单集合whiteList中,如果不在,返回false,!false为true,即执行{}中的代码
            resp.getWriter().write("{\"ok\":false ,\"reason\":\"不合法的访问\"}");
            return;
        }

        //...具体实现查看图片的代码...
    }
}

三、分类查看图片

在现在的图片服务器已经实现的功能里我们还只能一起看到所有的图片这样对于用户十分不方便,用户上传的图片较多时会导致用户查找某一张图片十分不方便,所以我们可以给图片加一个分类,再上传图片的时候选择图片分类,在查看图片时也能做到分类查看


1.思路:

1.数据库:

分类查看图片首先我们需要在数据库中存储下图片类型,所以数据库表的字段中要增加一列:sort

2.设计分类查找的前后端交互API

(1)请求:./ImageSortServlet?sort="类型"
(2)响应:
HTTP/1.1 200 OK
content-type:image/png
[图片的二进制内容]
{
“OK” : true;
}

3.Image

数据库中增加了一列sort,所以Image中必须增加sort这个变量,且必须有get、set、投String方法

4.from表单

后端需要储存图片的内容类型,但图片类型是需要用户在上传图片时选择的,所以我们需要在上传文件的from表单中加入选项,在用户上传图片时可以选择图片的类型

5.ImageDao类中原有方法

因为增加了图片内容类型这一元素,所以在往数据库中写入图片时需要同时写入图片的sort,同时查找图片时也要返回图片的类型sort

6.按照类型sort查找图片属性

ImageDao类中增加查找按照类型sort查找图片属性的方法selectSort(String sort)
这个方法的返回值应该该为List < Image >类型,因为一个类型的图片不止一个

7.ImageServlet 类

因为图片新增了一个类型变量,所以在获取from表单传来的数据时需要做一个处理
获取到里面的选项元素信息并且传给image的sort中

8.ImageSortServlet类

根据设计的前后端交互API我们需要一个查看不同图片类型的类
在这个类种重写doGet方法,用来查看图片

9.WEB.xml绑定URL

我们新增了ImageSortServlet类,要在WEB.xml中将ImageSortServlet类与对应的URL绑定

10.新建.html文件

根据图片内容类型的不同,我们可以创建不同的.html文件,作为不同类型图片展示的页面

11.index.html

更改前端主页面代码


2.数据库

列名含义类型备注
imageId图片的Idint不可重复,不可为空,自增(现实中用户无法设置图片的Id)
imageName图片名字varchaar(50)
size图片的大小int
uploadTime图片上传时间varc har(50)
contenType图片类型varchar(50HTTP响应头中的一个字段,用于定义文件的类型和网页编码,决定网页以什么形式读取文件
path图片路径varchar(1024)图片会以文件形式存在磁盘,数据库中记录下存储路径对应词攀上的图片
md5图片的校验和varchar(1024)用于提高该系统的安全性(通过一个更短的字符串来验证整体数据是否正确)
sort图片内容类型varchaar(50)用于保存图片的内容类型,用于分类查看图片

3.Image

在Image类增加下面的代码即可。(toString方法增加子段变为这样即可)

    private String sort;//图片类型
    public String getSort() {
        return sort;
    }
    public void setSort(String sort) {
        this.sort = sort;
    }
    public String toString() {
        return "Image{" +
                "imageId=" + imageId +
                ", imageName='" + imageName + '\'' +
                ", size=" + size +
                ", uploadTime='" + uploadTime + '\'' +
                ", contentType='" + contentType + '\'' +
                ", path='" + path + '\'' +
                ", md5='" + md5 + '\'' +
                ", sort='" + sort + '\'' +
                '}';
    }


4.from表单

在upload.html文件中更改上传文件的from表单,在from表单中增加一个选项,该选项只能单选,有以下几个选项:植物、动物、风光、人像、美食、其他这六个类别,该选项的名字为:options

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>上传文件</title>
</head>
<body>
<form id="upload-form" action="image" method="post" enctype="multipart/form-data" >
    <H2>这个文件的类型是:</H2>
    <select name="options">
        <option value="option1">植物</option>
        <option value="option2">动物</option>
        <option value="option3">风光</option>
        <option value="option4">人像</option>
        <option value="option5">美食</option>
        <option value="option6">其他</option>
    </select>
    <input type="file" id="upload" name="upload" />
    <br />
    <!--上传文件按钮-->
    <input type="submit" value="Upload" />
</form>
</body>
</html>

5.ImageDao类中原有方法

(1)更改insert方法:
更改SQL语句,增加一个占位符?
在给占位符传值是增加一行,传入sort
(2)更改select方法(selectAll等)
在处理结果集的时候记得处理sort


6.按照类型sort在数据库中查找图片属性

在ImageDao类中新增一个selectSort方法,传入参数为sort返回值为List< Image >,除了SQL语句其他都和selectMd5方法是一样的,SQL语句为按照sort查找数据库

    //按照sort查找数据库图片信息
    public List<Image> selectSort(String sort)throws SQLException {
        List<Image> images = new ArrayList<>();//查找所有的结果返回不止一条数据,所以用列表存放结果集
        Connection connection = DBUtil.getConnection();//建立数据库连接
        String SQL= "select * from image where sort = ?";//构造SQL语言
        PreparedStatement statement = null;//statement 用于拼接SQL语言
        ResultSet resultSet = null;
        try{
            statement = connection.prepareStatement(SQL);//拼接SQL语言
            statement.setString(1,sort);
            //执行SQL
            resultSet = statement.executeQuery();
            //处理结果集
            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"));
                image.setSort(resultSet.getString("sort"));
                images.add(image);
            }
            return images;
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement, resultSet);
        }
        return null;
    }


7.ImageServlet 类

在处理from表单中提交的options选项及文件时,注意后端代码接受参数的方法
from提交表单是采用二进制方式提交的,所以后端代码在处理时就需要判断每个参数的属性,文本就按照文本格式来处理,文件就按照文件格式处理,我们需要用到以下几个包:
pom.xml中加入以下包:

    <!-- https://mvnrepository.com/artifact/commons-io/commons-io有关图片文本同时上传 -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
    <dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.9.2</version>
    </dependency>

在ImageServlet 类的doPost方法中我们需要对获取到的from表单中的参数进行判断,判断是否是文本信息,然后进行分类处理,b便利表单提交过来的内容,使用Iterator迭代器来迭代遍历集合中的元素,将下一个元素存储于fileItem,然后用fileItem.isFormField()方法来判断该元素是不是一个表单字段,如果不是就按照文件处理,如果是就继续判断该元素的名字是不是"options",是就将该元素的值储存与sort中,最终代码如下:

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType("application/json;charset=utf-8");
        //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
            Image image = new Image();

            //遍历表单中提交过来的内容
            Iterator iterator = items.iterator();
            //创建一个迭代器对象,用于遍历集合中的元素
            //items: 这是一个集合对象,例如List或者Set,包含了一些元素
            //iterator(): 这是集合类的一个方法,用于创建一个迭代器对象。
            //Iterator iterator: 这是一个迭代器类型的变量,用于存储创建的迭代器对象。
            while (iterator.hasNext()) {
                FileItem fileItem = (FileItem) iterator.next();
                //iterator: 这是一个迭代器对象,用于遍历集合中的元素
                //next(): 这是迭代器的一个方法,用于获取集合中的下一个元素
                //FileItem fileItem: 这是一个FileItem类型的变量,用于存储从迭代器中获取的下一个FileItem对象。
                if (fileItem.isFormField()) { // 如果是表单域 ,就是非文件上传元素
                    //isFormField(): 这是 FileItem 类的一个方法,用于判断当前对象是否表示一个表单字段
                    // 如果当前对象是一个表单字段,那么这个方法将返回 true,否则返回 false。
                    String value = fileItem.getString("UTF-8");
                    if(fileItem.getFieldName().equals("options")){
                        image.setSort(value);
                    }
                }else {

                    //(3)将fileUpload解析得到的信息存入image
                    //取出items中存储的众多图片中的第一个图片的信息存储于fileItem
                    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());
                    //md5计算
                    image.setMd5(DigestUtils.md5Hex(fileItem.get()));
                    // 构造一个路径:./image+图片名,但是这个文件存储路径会导致文件名相同时文件路径就会相同,无法存储,所以可以在这个路径中加入时间戳(毫秒级)来分开两个文件
                    //使用md5作为文件路径
                    image.setPath("./image/" + image.getMd5());
                    ImageDao imageDao = new ImageDao();
                    //先查找存入图片的md5值是否在数据库中有相同的了,没有会返回空值,此时存入磁盘
                    List<Image> imageServletMd5 = imageDao.selectMd5(image.getMd5());
                    System.out.println(imageServletMd5);
                    if (imageServletMd5 == null || imageServletMd5.isEmpty()) {
                        //2.将图片内容存入磁盘
                        File file = new File(image.getPath());
                        //System.out.println(file);
                        try {
                            fileItem.write(file);
                            //System.out.println(fileItem);
                        } catch (Exception e) {
                            resp.setContentType("application/json;charset=utf-8");
                            resp.getWriter().write("{\"ok\":false ,\"reason\":\"写入磁盘失败\"}");
                        }

                    }
                    //(4)将数据存入数据库,利用imageDao中的insert方法
                    imageDao.insert(image);
                }
            }


        } 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.sendRedirect("index.html");
    }


8.ImageSortServlet类

新建ImageSortServlet类重写doGet方法,作为按照类型查看图片时触发的类(API中设置分类查看图片的方法为GET方法)
当前方法需要获取URL中的sort信息,用该信息来查找图片

public class ImageSortServlet extends HttpServlet {

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf-8");
        String sort = req.getParameter("sort");
        if (sort == null || sort.equals("")){
            resp.setContentType("application/json;charset=utf-8");
            resp.getWriter().write("{\"ok\":false ,\"reason\":\"sort为空\"}");

        }else {
            ImageDao imageDao = new ImageDao();
            try {
                List<Image> images = imageDao.selectSort(sort);
                Gson gson = new GsonBuilder().create();
                String jsonData = gson.toJson(images) ;
                //3.将Json字符串写入返回值resp中
                resp.getWriter().write(jsonData);

            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

9.WEB.xml绑定URL

绑定ImageSortServlet与出发该类的URL/imageSelectSort

  <servlet>
    <!--定义了一个叫ImageShowServlet的类映射到URL路径:/imageShow-->
    <servlet-name>ImageSortServlet</servlet-name>
    <!--ImageShowServlet类的完全限定名-->
    <servlet-class>api.ImageSortServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ImageSortServlet</servlet-name>
    <!--URL路径:/imageShow-->
    <url-pattern>/imageSelectSort</url-pattern>
  </servlet-mapping>

10.新建.html文件

按照前面的分类我们需要六个不同查看类型图片的页面

名称文件名
植物other.html
动物animal.html
风光Scenery.html
人像portrait.html
美食delicacy.html
其他other.html

other.html:
注意ajax中的URL记得更改:url:“imageSelectSort?sort=option6”
option6是因为在我们进行数据库存储时图片的内容类型就设置成了option1-option6,分别代表对应的不同的类别,具体对应请看upload.html文件

<!DOCTYPE html>
<html>
<head>
    <!-- Your site title -->
    <title>大饼的图片服务器-其他</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="description" content="Your site description" />

    <!-- Favicon Image. -->
    <link rel="icon"  type="image/x-icon" />

    <!-- Google Web Font. -->
    <link href="https://fonts.googleapis.com/css?family=Lato:700,300" rel="stylesheet" type="text/css">

    <!-- Normalize v.3.0.0 - makes browsers render all elements more consistently. -->
    <link rel="stylesheet" type="text/css" href="css/normalize.min.css" />

    <!-- Stylesheet - to improve site's load speed, better use the minimized version.
         The unminified version is also included in package. -->
    <link rel="stylesheet" type="text/css" href="css/style.lite.min.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js"></script>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>



</head>

<body id="parent">
<div class="main-container">
    <div class="header">
        <div class="clearfix">
            <div class="float-left logo">
                <h1>
                    <a href="#">
                        大饼的图片服务器-其他
                    </a>
                </h1>
            </div>
            <div class="float-right">
                <ul id="top-nav" class="slimmenu">
                    <li>
                        <a href="./upload.html" >上传文件</a>
                    </li>
                    <li>
                        <a href="#">分类</a>
                        <ul>

                            <li>
                                <a href="./index.html" class="filter-label" data-filter=".cat-1">所有</a>
                            </li>
                            <li>
                                <a href="./plant.html" class="filter-label" data-filter=".cat-1">植物</a>
                            </li>
                            <li>
                                <a href="./animal.html" class="filter-label" data-filter=".cat-2">动物</a>
                            </li>
                            <li>
                                <a href="./Scenery.html" class="filter-label" data-filter=".cat-3">风光</a>
                            </li>
                            <li>
                                <a href="./portrait.html" class="filter-label" data-filter=".cat-1">人像</a>
                            </li>
                            <li>
                                <a href="./delicacy.html" class="filter-label" data-filter=".cat-2">美食</a>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <a href="#" class="fullscreen tooltip" title="Go Full Screen">
                            <span class="pictogram">&#xe801;</span>
                        </a>
                        <a href="#" class="fullscreenExit tooltip" title="Exit Full Screen">
                            <span class="pictogram">&#xe802;</span>
                        </a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</div>
<div id="freewall" class="free-wall" >
    <div id ="image" >
        <div v-for="image in images" >
            <div  class="brick tint size11 cat-2">
                <img v-bind:src = "'imageShow?imageId='+image.imageId" alt="" />
                <div class="overlay">
                    <h3 cla ss="project-title">欢迎查看其他类型图片</h3>
                    <p class="project-description">这张图片是{{image.imageName}}</p>
                    <a  class="open-project" v-on:click="remove(image.imageId)"><span class="pictogram">&#9842;</span> 删除</a>
                </div>

            </div>

        </div>
    </div>



</div>

<!-- All links from this homepage will be opened in this iframe, to prevent fullscreen (if enabled) from exiting if the user clicked on a link. -->
<iframe id="open-iframe" name="open-iframe"></iframe>

<!-- Scripts -->
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="js/freewall.min.js"></script>
<script type="text/javascript" src="js/jquery.cycle2.min.js"></script>
<script type="text/javascript" src="js/jquery.slimmenu.min.js"></script>
<script type="text/javascript" src="js/custom-script.min.js"></script>
<script>
        var app = new Vue({
            el:'#image',
            data:{
                images: [
                ]
            },
            methods:{
                //GET/image
                getImages(){
                    $.ajax({
                        url:"imageSelectSort?sort=option6",
                        type:"get",
                        context:this,
                        success:function(data,status){
                        //发送请求成功的情况下执行,将获取到的返回值传给images
                            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>

11.index.html

记得在右上角加入查看不同图片的跳转链接,每个类的页面上也要放上这个链接,用来跳转

                    <li>
                        <a href="#">分类</a>
                        <ul>

                            <li>
                                <a href="./index.html" class="filter-label" data-filter=".cat-1">所有</a>
                            </li>
                            <li>
                                <a href="./plant.html" class="filter-label" data-filter=".cat-1">植物</a>
                            </li>
                            <li>
                                <a href="./animal.html" class="filter-label" data-filter=".cat-2">动物</a>
                            </li>
                            <li>
                                <a href="./Scenery.html" class="filter-label" data-filter=".cat-3">风光</a>
                            </li>
                            <li>
                                <a href="./portrait.html" class="filter-label" data-filter=".cat-1">人像</a>
                            </li>
                            <li>
                                <a href="./delicacy.html" class="filter-label" data-filter=".cat-2">美食</a>
                            </li>
                        </ul>
                    </li>

12.加入白名单

记得将新建的几个页面的URL加入查看图片的白名单中

    static private HashSet<String> whiteList = new HashSet<>();
    //创建一个静态私有HashSet集合类型为String,名为whiteList
    static {
        //在静态块中初始化whiteList这个静态私有HashSet集合
        whiteList.add("http://127.0.0.1:8080/img/index.html");
        whiteList.add("http://127.0.0.1:8080/img/plant.html");
        whiteList.add("http://127.0.0.1:8080/img/animal.html");
        whiteList.add("http://127.0.0.1:8080/img/Scenery.html");
        whiteList.add("http://127.0.0.1:8080/img/portrait.html");
        whiteList.add("http://127.0.0.1:8080/img/delicacy.html");
        whiteList.add("http://127.0.0.1:8080/img/other.html");
    }

感谢您对大饼的支持
今天的你也很辛苦,晚安,明天见

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1038238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DevExpress WinForms图表组件 - 直观的数据信息呈现新方式!(一)

凭借界面控件DevExpress WinForms全面的2D和3D图表类型的集合&#xff0c;DevExpress WinForms的图表控件设计大大简化了开发者直观地向最终用户呈现信息的方式。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能完…

[python 刷题] 739 Daily Temperatures

[python 刷题] 739 Daily Temperatures 题目&#xff1a; Given an array of integers temperatures represents the daily temperatures, return an array answer such that answer[i] is the number of days you have to wait after the ith day to get a warmer temperatur…

记一次实战案例

1、目标&#xff1a;inurl:news.php?id URL&#xff1a;https://www.lghk.com/news.php?id5 网站标题&#xff1a;趋时珠宝首饰有限公司 手工基础判断&#xff1a; And用法 and 11: 这个条件始终是为真的, 也就是说, 存在SQL注入的话, 这个and 11的返回结果必定是和正常页…

修改vscode底部栏背景和字体颜色

修改vscode底部栏背景和字体颜色 如图&#xff1a; 首先打开齿轮&#xff0c;打开设置搜索workbench.colorCustomizations,然后点击编辑setting.json修改setting.json内内容 "workbench.colorCustomizations": {"statusBar.foreground": "#FFFFFF…

为什么u盘在mac上显示不出来

插入U盘是个看似简单的操作&#xff0c;但有时候在Mac电脑上却出现了无法显示U盘的情况。这样的问题是非常让人头疼的&#xff0c;特别是当你急需使用U盘中的文件时。那么&#xff0c;究竟为什么U盘在Mac上会显示不出来呢&#xff1f;今天就让我们一起来深入了解一下这个问题&a…

OR54 字符串中找出连续最长的数字串

目录 一、题目 二、解答 &#xff08;一&#xff09;问题一&#xff1a;在记录完一组连续字符串后&#xff0c;没有注意判别紧随其后的非数字字符 &#xff08;二&#xff09;问题二&#xff1a;越界访问 &#xff08;三&#xff09;正确 一、题目 字符串中找出连续最长的…

powerDesigner 的基本使用

打开powerDesigner 新建 PDM(物理数据模型) 添加表字段 双击表&#xff0c;设置ID自增 选择导出数据库表SQL 导出成功 使用三方工具连接数据库&#xff0c;然后运行对应SQL文件即可 导入SQL文件数据到powerDesigner

Ae 效果:CC Tiler

扭曲/CC Tiler Distort/CC Tiler CC Tiler &#xff08;CC 平铺器&#xff09;主要用于将图像以平铺的方式重复显示&#xff0c;可以创建有趣的复制和平铺的视觉效果。 平铺的范围限制在图层大小。如果想在合成大小内进行平铺&#xff0c;最简单的方法是先将源图像&#xff08;…

【数据结构】逻辑结构与物理结构

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 根据视点的不同,我们把数据结构分为逻辑结构和物理结构. &#x1f333;逻辑结构 逻辑结构:是指数据对象中数据元素之间的相互关系. 逻辑结构分为以下四种: 1.集合结构 集合结…

计算机中实数的比较

计算机中实数的比较 最近被问到了实数与0为什么不能直接比较的问题&#xff0c;要想说清楚还真不容易。 这里从浮点数的表示、内存存储角度加以总结。 科学计数法 科学计数法表示十进制数的浮点数遵循了小数点前面只有一个数&#xff08;1~9&#xff09;的规则。 例如&…

python+nodejs+php+springboot+vue 法律知识分享科普系统平台

在设计过程中&#xff0c;充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 要想实现法律知…

93 # 实现 express 错误处理中间件

上一节实现了 express 的中间件&#xff0c;这一节来实现错误处理中间件 执行某一步出错了&#xff0c;统一规定调用 next 传递的参数就是错误信息 先看 express 实现的demo const express require("express"); const app express();app.use("/", (re…

2023-09-23 Windows系统rust开发环境配置真经

Windows系统rust开发环境配置真经 前言一、配置C编译链和VsCode二、安装rust编译工具三、配置VsCode一. 安装rust-analyzer插件二. 安装Error Lens插件三. 安装Even Better TOML插件四. 配置 launch.json五. 配置 tasks.json六. 配置 Cargo.toml 总结 前言 有了配置C语言环境的…

腾讯mini项目-【指标监控服务重构】2023-08-27

今日已办 Docker Monitoring with cAdvisor, Prometheus and Grafana Docker Monitoring with cAdvisor, Prometheus and Grafana | by Mertcan Simsek | MediumMonitoring Docker container metrics using cAdvisor | Prometheus prometheus.yml global:scrape_interval: …

Linux下安装使用Redis

1.进入/usr/local目录&#xff0c;新建一个目录redis&#xff0c;下载redis安装包 wget https://download.redis.io/releases/redis-6.2.6.tar.gz**并解压 tar xzf redis-6.2.6.tar.gz进入redis-6.2.6目录 cd redis-6.2.6用make来编译 make2.启动redis: ./src/redis-server…

Vue-devTools安装—创建项目方法2 ui创建——Vue指令综合案例——汽车品牌管理

目录 项目源代码&#xff1a; 一、vue-devTools安装 二、案例功能实现 1、新建项目&#xff08;ui创建&#xff09; 2、cnpm导入项目依赖库 3、删除不需要的代码结构: 4、修改代码结构 5、添加汽车品牌 插件安装 bootstrap的提示功能 添加bootstrap样式 6、删除汽车品牌…

ndoe.js、npm相关笔记

1、npm 全局安装 npm config get prefix 获取 npm 全局安装路径如果全局插件不能正常使用&#xff0c;看环境变量是否已经配置。没有配置则把全局安装路径配置到环境变量的path中

【golang】调度系列之sysmon

调度系列 调度系列之goroutine 调度系列之m 调度系列之p 在golang的调度体系中&#xff0c;除了GMP本身&#xff0c;还有另外一个比较重要的角色sysmon。实际上&#xff0c;除了GMP和sysmon&#xff0c;runtime中还有一个全局的调度器对象。但该对象只是维护一些全局的数据&…

高云FPGA系列教程(10):letter-shell串口终端移植

文章目录 1. letter-shell简介2. letter-shell源码获取3. letter-shell移植4. 函数和变量应用示例本文是高云FPGA系列教程的第10篇文章。 shell,中文是外壳的意思,就是操作系统的外壳。通过shell命令可以操作和控制操作系统,比如Linux中的Shell命令就包括ls、cd、pwd等等。总…

leetcode100----双指针

283. 移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1:输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2:输入: nums …