SSM+Ajax实现广告系统

news2024/11/14 19:02:35

文章目录

    • 1.案例需求
    • 2.编程思路
    • 3.案例源码(这里只给出新增部分的Handler和ajax部分,需要详情的可以私信我)
    • 4.小结

1.案例需求

使用SSM+Ajax实现广告系统,包括登录、查询所有、搜索、新增、删除、修改等功能,具体实现的效果图如下:
在这里插入图片描述

2.编程思路

  • 登录:
    • 前端处理

      • 使用jQuery的$.ajax方法,在用户点击提交按钮时(阻止表单的默认提交行为),向服务器发送POST请求。请求的URL设置为"login.action",这是Spring MVC中@RequestMapping注解映射的URL。通过data属性将表单中的数据(用户名和密码)以JSON格式发送给服务器。在success回调函数中处理服务器返回的响应数据。
    • 后端处理

      • 使用@RequestMapping(“login.action”)注解定义处理登录请求的URL。login方法接收前端发送的用户名(advTitle)、密码,以及用于响应的ResponseVO对象和HttpSession对象。调用服务层(advService)的login方法验证用户名和密码。根据验证结果设置ResponseVO对象的code和message属性,并将验证成功的用户信息存入HttpSession中以便后续使用。将ResponseVO对象作为方法的返回值,Spring MVC会自动将其序列化为JSON格式返回给前端。
  • 查询:
    • 前端处理
      • 页面加载时,通过AJAX请求selectCategoryName接口获取所有广告分类的名称,并使用JavaScript动态生成下拉列表()的选项。这样用户就可以在下拉列表中选择广告分类,作为查询条件之一。页面加载后,可能还需要执行一次初始查询,以展示默认的广告信息列表。这可以通过另一个AJAX请求queryInfos.action(不带任何查询参数或使用默认参数)来实现。查询结果通过addRow函数动态添加到表格中。提供一个查询按钮(#btn)或表单提交事件,用于在用户输入查询条件(如广告标题、分类ID)后触发查询操作。点击查询按钮时,阻止表单的默认提交行为,并通过AJAX请求queryInfos.action接口,将查询条件(advTitle和categoryId)作为请求参数发送。接收响应数据后,根据状态码(code)判断查询是否成功,并更新页面内容:如果查询成功,则清空表格并重新添加查询结果;如果查询失败,则显示错误信息。
    • 后端处理
      • 在后端,通过@RequestMapping注解定义了两个查询接口:queryAdvInfos用于根据广告标题(advTitle)和分类ID(categoryId)查询广告信息,queryAdvCategoryNames用于查询所有广告分类的名称。queryAdvInfos方法接收两个参数(advTitle和categoryId),并使用这些参数构建一个查询条件对象(AdvVo),然后调用服务层(advService)的queryAdvsInfo方法执行查询,最后根据查询结果构建响应数据并返回。queryAdvCategoryNames方法直接调用服务层(advCategoryService)的queryAllCategoryNames方法查询所有广告分类的名称,并将结果构建为响应数据返回。对于查询结果,后端使用Map<String, Object>来构建响应数据,其中可能包含状态码(code)、消息信息(INFO或错误信息)、以及查询结果列表(如advInfo_List或advCategoryName_List)。
  • 新增:
    • 前端分析
      • 通过AJAX请求selectCategoryName接口获取广告分类列表,并动态添加到分类选择器中。设置默认过期时间:页面加载时计算下个月的今天作为默认过期时间,并设置到相应的输入框中。使用event.preventDefault()阻止表单的默认提交行为,改为通过AJAX异步提交。创建一个FormData对象,将表单字段和文件数据添加到其中。通过AJAX将FormData对象发送到add.action接口。设置processData和contentType为false,因为FormData对象会自动处理这些设置。根据后端返回的数据显示操作结果,如果添加成功则跳转到广告列表页面。
    • 后端处理
      • 使用@RequestMapping(“/add.action”)注解定义了一个处理广告添加的HTTP POST请求接口。通过@ResponseBody注解表明该接口返回的数据会直接写入HTTP响应体(body)中,而不是解析为跳转路径或视图名称。接收多个参数,包括HttpServletRequest、MultipartFile(用于文件上传)、广告标题、分类ID、过期时间、广告内容、备注和密码。特别注意MultipartFile用于处理文件上传,其他参数则是普通的表单数据。对过期时间expiredTime进行非空和格式校验,确保用户输入了有效的日期字符串。创建一个临时文件来存储上传的文件,避免直接处理原始输入流可能带来的问题。将上传的文件内容复制到临时文件中,并从临时文件复制到服务器的两个不同位置(可能用于备份或不同的访问路径)。最后,删除临时文件以释放资源。将接收到的数据封装到AdvInfo对象中。调用advService.add(advInfo)方法将广告信息保存到数据库或持久化存储中。根据操作结果返回相应的状态码和信息。
  • 删除:
    • 前端处理:
      • 使用 this.id 获取广告ID,并将其存储在localStorage中,发起一个AJAX POST请求到 “delete.action” URL,携带要删除的广告ID(advId)。在AJAX请求成功后,清空表格体(#myTbody)和消息区域(#msg),并显示服务器返回的消息。如果服务器返回的 code 为200(表示删除成功),则尝试重定向到 “adsList.html” 页面。
    • 后端处理:
      • 接收 advId 和 responseVO 作为参数。调用 advService.deleteAdvById(advId) 来执行删除操作,并根据返回的结果设置 responseVO 的 code 和 message 属性。返回 responseVO 对象。
  • 修改:
    • 前端处理:
      • 通过 localStorage.getItem(“advId”) 获取要修改的广告的ID。使用AJAX请求到 /queryAdvById.action,传递广告ID作为参数。在AJAX请求的 success 回调中,将返回的广告信息填充到表单的相应字段中。对于下拉选择框,需要遍历选项并设置选中的值。监听修改按钮的点击事件,阻止表单的默认提交行为。使用 FormData 对象收集表单数据,包括文件上传。发起AJAX POST请求到 /update.action,发送 FormData 对象。设置 processData 和 contentType 为 false,以允许发送文件。在AJAX请求的 success 回调中,根据返回的数据显示消息,并在成功时重定向到广告列表页面。
    • 后端处理:
      • 使用 @RequestMapping(“/update.action”) 注解的方法接收来自前端的POST请求。方法参数包括 HttpServletRequest、MultipartFile(用于文件上传)、以及其他表单字段。从请求中提取广告ID、标题、类别ID、过期时间、内容、备注、密码和文件等参数。对过期时间进行解析,并处理可能的 ParseException 和 NullPointerException。将上传的文件先保存到临时文件中。定义两个目标路径,并将文件从临时文件复制到这两个位置。更新广告对象中的图片路径。删除临时文件。创建一个 AdvInfo 对象,并设置其属性。调用服务层方法 advService.update(advInfo) 来更新数据库中的广告信息。根据服务层方法的返回值,构造一个包含状态码和消息的 Map 对象。使用 @ResponseBody 注解将 Map 对象转换为JSON格式,并发送给前端。

3.案例源码(这里只给出新增部分的Handler和ajax部分,需要详情的可以私信我)

Handler类:

	@Resource(name = "advServiceImpl")
    private AdvService advService;

    @Resource(name = "advCategoryServiceImpl")
    private AdvCategoryService advCategoryService;
 	@RequestMapping("/add.action")
    @ResponseBody
    public Map<String,Object>  add(HttpServletRequest request, MultipartFile uploadFile,String advTitle, Integer categoryId, String expiredTime, String advContent, String remark,String password) throws IOException, ParseException {

        Map<String,Object> map = new HashMap<>();
        AdvInfo advInfo = new AdvInfo();

        advInfo.setAdvTitle(advTitle);
        advInfo.setCategoryId(categoryId);
        advInfo.setAdvContent(advContent);
        advInfo.setRemark(remark);
        advInfo.setPassword(password);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date time =null;
        if (expiredTime == null || expiredTime.isEmpty()) {
            throw new IllegalArgumentException("expiredTime cannot be null or empty");
        }
        try {
            time = dateFormat.parse(expiredTime);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        advInfo.setExpiredTime(time);

        // 获取Web应用程序的根目录的绝对路径
        String realPath = request.getSession().getServletContext().getRealPath("");

        // 创建临时文件
        File tempFile = null;
        try {
            tempFile = File.createTempFile("upload", ".tmp");
        } catch (IOException e) {
            // 处理异常情况
            e.printStackTrace();
        }

        // 将上传的文件传输到临时文件
        try {
            uploadFile.transferTo(tempFile);
        } catch (IOException e) {
            // 处理异常情况
            e.printStackTrace();
        }

        // 设置图片信息
        String originalFilename = uploadFile.getOriginalFilename();
        advInfo.setImg("images\\" + originalFilename);

        // 定义两个不同的目标路径
        String path1 = realPath + File.separator + "images" + File.separator + originalFilename;

        String path2 = "D:" + File.separator +
                "SoftWare" + File.separator +
                "fs" + File.separator +
                "case" + File.separator +
                "Ajax-advSystem" + File.separator +
                "Ajax-advSystem" + File.separator +
                "src" + File.separator +
                "main" + File.separator +
                "webapp" + File.separator +
                "images"+File.separator + originalFilename;

        // 从临时文件复制到第一个位置
        try {
            FileUtils.copyFile(tempFile, new File(path1));
        } catch (IOException e) {
            // 处理异常情况
            e.printStackTrace();
        }

        // 从临时文件复制到第二个位置
        try {
            FileUtils.copyFile(tempFile, new File(path2));
        } catch (IOException e) {
            // 处理异常情况
            e.printStackTrace();
        }

        // 删除临时文件
        if (tempFile != null && tempFile.exists()) {
            tempFile.delete();
        }


        int result = advService.add(advInfo);
        if (result > 0) {
            map.put("code",200);
            map.put("INFO", "添加广告成功");
        } else {
            map.put("code",100);
            map.put("INFO", "添加广告失败");
        }
        return map;
    }

ajax:

  $(function () {
    //获取id为empdeptno的元素
    var objselect = document.getElementById("categoryId");
    $.ajax({
      url: "selectCategoryName",
      type: "post",
      success: function (data) {
        for (var i = 0; i < data.advCategoryName_List.length; i++) {
          var advCategoryName = data.advCategoryName_List[i];
          objselect.add(new Option(advCategoryName.categoryName, advCategoryName.categoryId));
        }
      },
      dataType:"json"
    });
  });

  $(function () {
    // 设置过期时间为下个月的今天
    var today = new Date();
    today.setMonth(today.getMonth() + 1); // 设置为下个月
    var expiryDate = today.getFullYear() + '-' +
            ('0' + (today.getMonth() + 1)).slice(-2) + '-' +
            ('0' + today.getDate()).slice(-2); // 格式化为 YYYY-MM-DD

    // 设置输入框的值
    $("#expiredTime").val(expiryDate);

    $("#btn").click(function (event) {
      event.preventDefault();//阻止表单的默认提交行为

      var formdata = new FormData();
      formdata.append("advTitle",$("#advTitle").val());
      formdata.append("categoryId",$("#categoryId").val());
      formdata.append("expiredTime",$("#expiredTime").val());
      formdata.append("advContent",$("#advContent").val());
      formdata.append("remark",$("#remark").val());
      formdata.append("password",$("#password").val());
      formdata.append("uploadFile",document.getElementById("file").files[0]);

      $.ajax({
        url: "add.action",
        type: "post",

        data:formdata,
        processData:false,//发送二进制大数据
        contentType:false,

        success: function (data) {
          $("#mess").html(data.INFO);
          if (data.code == 200) {
            window.location.href = "http://localhost:8080/Ajax_advSystem/adsList.html";
          }
        },
        dataType: "json"
      });
    });
  });

4.小结

  • SSM是指Spring、SpringMVC和MyBatis这三个框架的集合,它们通常一起使用来构建Java Web应用程序。Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
  • SSM框架的重点知识:
    • Spring框架:控制反转(IoC)和依赖注入(DI): 理解如何通过Spring容器管理对象的生命周期和依赖关系。
    • 面向切面编程(AOP): 掌握如何在运行时将横切关注点织入到应用程序中。
    • 事务管理: 理解Spring对事务的支持,包括声明式事务管理。
    • 数据访问: 熟悉Spring的数据访问策略,包括JdbcTemplate和事务管理。
  • SpringMVC框架:
    • MVC架构: 理解模型(Model)、视图(View)和控制器(Controller)的概念和它们在Spring MVC中的实现。
    • 请求处理: 掌握如何通过@Controller和@RequestMapping注解来处理HTTP请求。
    • 数据绑定和验证: 理解如何将请求参数绑定到Java对象,并进行数据验证。
    • 视图解析: 熟悉如何配置视图解析器以及如何返回视图。
  • MyBatis框架:
    • SQL映射: 理解MyBatis如何将SQL语句映射到Java方法上。
    • 配置和映射文件: 掌握MyBatis配置文件和映射文件的编写。
    • 动态SQL: 学会使用MyBatis的动态SQL功能来编写灵活的SQL语句。
    • 插件开发: 了解如何通过MyBatis插件来扩展或增强MyBatis的功能。
  • Ajax的重点知识:
    • XMLHttpRequest对象:创建和使用XMLHttpRequest对象来发送异步请求。
    • 异步请求:理解Ajax的工作原理,包括如何发送请求、处理响应以及更新网页的某部分。
    • 数据格式:熟悉JSON和XML等数据格式,并掌握如何在Ajax中发送和接收这些格式的数据。
    • 事件处理:掌握如何在JavaScript中处理事件,如按钮点击事件,触发Ajax请求。

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

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

相关文章

『功能项目』状态模式转换场景【30】

本章项目成果展示 打开上一篇29Unity本地数据库读取进入游戏的项目&#xff0c; 本章要做的事情是通过状态者模式转换场景&#xff0c;在进入账号登陆界面前闪烁显示Logo 首先创建一个新的场景命名为StartUI 修改游戏场景名字 重命名为FightGame01 首先创建一个脚本文件夹&…

gazebo可能打不开的问题

如果经常遇到gazebo只能断网才能运行的时候&#xff0c;主要就是因为无法联网访问gazebo的在线模型库&#xff0c;此时我们一般无法在联网的情况下打开gazebo。 这个时候就直接将下载好的模型先放到~/.gazebo/models/文件夹下面即可&#xff1a; https://github.com/osrf/gazeb…

RTOS Sensor Framework对比

1.背景 传感器(Sensor)是物联网(IOT)的重要组成部分&#xff0c;用于感知和采集环境中的各种数据&#xff0c;大部分智能硬件都需要。 为使传感器能正常⼯作&#xff0c;驱动开发者需要开发不同的驱动程序&#xff0c;驱动程序要实现芯片寄存器\IO设置&#xff0c;又要响应使用…

搭建 canal 监控mysql数据到 elasticsearch 中(本机到远端sql)

搭建 canal 监控mysql数据到 elasticsearch 中&#xff08;本机到远端sql&#xff09; 需求: 要将 MySQL 数据库 info 中的 notice 和 result 表的增、删、改操作同步到 Elasticsearch 的 notice 和 result 索引&#xff0c;您需要正确配置 MySQL、Canal 、Canal Adapter 、 …

3--Web前端开发-前端工程化,vue项目

目录 端口配置 element 快速入门 table表格组件 分页组件 Dialog对话框组件 表单组件 端口配置 在vue.config.js中更改 源代码为 const { defineConfig } require(vue/cli-service) module.exports defineConfig({transpileDependencies: true })更改为 const { def…

Linux——redis主从复制、哨兵模式

一、redis 的安全加固&#xff1a; 对redis数据库访问的角度 auth // 验证登录redis 数据库的用户acl // 设置redis用户的权限将配置完成的ACL策略写入配置文件 config rewrite //目前redis生效的配置全部写入到默认配置文件的尾部写入到acl文件中&#xff0c;在加载配置文件时…

《论软件设计模式及其应用》通关范文,软考高级系统架构设计师

论文真题 设计模式(Design Pattern)是一套被反复使用的代码设计经验总结,代表了软件开发人员在软件开发过程中面临的一般问题的解决方案和最佳实践。使用设计模式的目的是提高代码的可重用性,让代码更容易被他人理解,并保证代码可靠性。现有的设计模式已经在前人的系统中…

每日一练:和为K的子数组

一、题目要求 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#xff1a; 输入&#xff1a;n…

python深度学习:从注意力机制到生成模型,全面解析现代AI技术

近年来&#xff0c;伴随着以卷积神经网络&#xff08;CNN&#xff09;为代表的深度学习的快速发展&#xff0c;人工智能迈入了第三次发展浪潮&#xff0c;AI技术在各个领域中的应用越来越广泛。注意力机制、Transformer模型&#xff08;BERT、GPT-1/2/3/3.5/4、DETR、ViT、Swin…

OpenCV结构分析与形状描述符(10)检测并提取轮廓函数findContours()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在二值图像中查找轮廓。 该函数使用算法 253从二值图像中检索轮廓。轮廓是有用的工具&#xff0c;可用于形状分析和对象检测与识别。参见 OpenC…

SDN架构详解

目录 1&#xff09;经典的IP网络-分布式网络 2&#xff09;经典网络面临的问题 3&#xff09;SDN起源 4&#xff09;OpenFlow基本概念 5&#xff09;Flow Table简介 6&#xff09;SDN的网络架构 7&#xff09;华为SDN网络架构 8&#xff09;传统网络 vs SDN 9&#xf…

网络安全与恶意攻击:如何应对?

引言 随着技术的发展&#xff0c;我们的生活越来越依赖于网络。但是&#xff0c;这也暴露了我们的系统对各种网络威胁的脆弱性。无论是个人还是企业&#xff0c;网络安全都成为了我们不能忽视的话题。 网络威胁的类型 网络威胁主要有以下几种&#xff1a; 网络钓鱼攻击&#…

linux学习--第四天

--linux文件操作 文件IO操作包括&#xff1a; &#xff08;注&#xff1a;I&#xff1a;input&#xff08;输入&#xff09;O&#xff1a;output&#xff08;输出&#xff09;&#xff09; open&#xff1a;打开 close&#xff1a;关闭 read&#xff1a;读取 write&#xff1a;…

c++一个数因子和(快速求解)

void 一个数因子和(int 整数) {//缘由https://ask.csdn.net/questions/1054457#answer_1251715int he 0, j 0; string a "";while (j < 整数)if (!(整数%j))he j, a to_string(j) "";cout << a << "的因子和&#xff1a;" …

如何在 Java 应用程序中定位高 CPU 使用率问题

文章目录 ♨ 前言♨ 提前准备♨ 线上定位♨ 结语 ♨ 前言 在运行 Java 应用程序的服务器上&#xff0c;高 CPU 使用率可能会影响应用程序的性能和稳定性。本文将介绍如何通过一系列步骤和工具来准确诊断和解决高 CPU 使用率问题&#xff0c;特别是针对 Java 环境下的应用程序。…

OpenCV影像数据处理入门-学习篇

目录 简介如何安装图像数据处理简单操作视频数据处理简单操作 一、简介 在计算机视觉项目的开发中&#xff0c;OpenCV作为最大众的开源库&#xff0c;拥有了丰富的常用图像处理函数库&#xff0c;可用于开发实时的图像处理、计算机视觉以及模式识别程序。采用C/C语言编写&am…

用于辅助视障人士检测人行道障碍物的 TinyML 模型

这篇论文的标题为《A TinyML model for sidewalk obstacle detection: aiding the blind and visually impaired people》&#xff0c;发表在《Multimedia Tools and Applications》上。以下是论文的主要内容概述&#xff1a; 摘要&#xff1a; 论文介绍了在资源受限的物联网…

C语言程序设计 笔记代码梳理 重制版

前言 第1章 C语言的流程 1.C程序经历的六个阶段 编辑(Edit)预处理(Preprocess)编译(Compile)汇编(Assemble)链接(Link)执行(Execute) 2.C语言编写代码到运行 都是先编译&#xff0c;后链接&#xff0c;最后运行。&#xff08;.c ---> .obj --->.exe&#xff09;这个过…

热老化的行业应用

热老化应用行业&#xff1a;深度解析与图像呈现 热老化&#xff0c;作为一种重要的材料测试方法&#xff0c;在众多行业中扮演着关键角色。它通过模拟产品在高温环境下的长期使用&#xff0c;提前发现潜在的材料缺陷、性能衰退等问题&#xff0c;从而提高产品的可靠性&#xf…

打造个性化时装购物平台:Spring Boot框架的实践

第1章 绪论 1.1背景及意义 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。人们生活水平的不断提高&#xff0c;日常生活中人们对时装购物系统方面的要求也在不断提高&#xff0c;喜欢购物的人数更是不断增加&#xff0c;使得时装购物系统的开发成为必需而且紧迫的…