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请求。