扩展:构建ssm项目,使用ajax请求实现layui单表的查询和添加
'# 扩展:构建SSM项目,使用Ajax请求实现layui单表的查询和添加
一、背景与问题
在企业级开发中,SSM框架(Spring + Spring MVC + MyBatis)因其成熟稳定的特点,仍然是主流的Java Web开发方案。而layui作为国内优秀的前端框架,因其模块化、组件化的特点,广泛应用于管理后台系统。在实际开发中,单表的查询和添加操作是基础功能,但传统的页面刷新方式存在明显的用户体验短板。
本篇将深入探讨如何通过Ajax技术实现layui单表的无刷新查询和添加功能,重点分析其工作原理、实现细节、性能优化方案以及常见问题的解决方案。
二、基本原理
1. Ajax请求机制
Ajax(Asynchronous JavaScript and XML)通过XMLHttpRequest对象实现异步通信,核心流程包括:
- 前端通过JavaScript发送异步请求
- 后端接收请求并处理业务逻辑
- 后端返回JSON数据
- 前端解析数据并更新DOM
2. layui表格组件特性
layui的table模块支持:
- 异步加载数据(通过
layui.use初始化) - 动态更新数据(通过
table.reload方法) - 自定义列模板(
templet属性) - 分页控制(
page参数)
3. 跨域处理
当前后端分离时,需配置CORS(跨域资源共享)策略,主要通过以下方式实现:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.exposedHeaders("Content-Type")
.allowCredentials(true);
}
}三、环境准备
1. 项目依赖(Spring Boot 2.7 + MyBatis Plus)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>2. 前端依赖(layui 2.6.8)
<link href="https://www.layui.org/css/layui.css" rel="stylesheet">
<script src="https://www.layui.org/layui.js"></script>四、核心实现
1. 前端页面(layui单表查询)
<div class="layui-container">
<button class="layui-btn" id="addBtn">添加用户</button>
<table id="userTable" lay-filter="userTable"></table>
</div>
<script>
layui.use(['table', 'form'], function(){
var table = layui.table;
var $ = layui.$;
// 查询接口
function queryUsers(page, limit) {
$.ajax({
url: '/api/users',
type: 'GET',
data: {page: page, limit: limit},
success: function(res){
table.reload('userTable', {
page: {curr: page},
data: res.data
});
}
});
}
// 初始化表格
table.render({
elem: '#userTable',
url: '/api/users',
cols: [[
{type: 'checkbox'},
{field: 'id', title: 'ID'},
{field: 'name', title: '姓名'},
{field: 'email', title: '邮箱'}
]],
page: true
});
// 添加按钮事件
$('#addBtn').on('click', function(){
layer.open({
type: 1,
area: ['500px', '300px'],
content: '<div><input type="text" id="name" placeholder="姓名"><br>'+
'<input type="email" id="email" placeholder="邮箱"><br>'+
'<button id="submitBtn">提交</button></div>'
});
$('#submitBtn').on('click', function(){
$.ajax({
url: '/api/users',
type: 'POST',
data: {
name: $('#name').val(),
email: $('#email').val()
},
success: function(res){
layer.msg('添加成功');
queryUsers(1, 10);
}
});
});
});
});
</script>2. 后端接口实现(Spring Boot)
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public Result queryUsers(@RequestParam int page, @RequestParam int limit) {
return Result.success(userService.pageQuery(page, limit));
}
@PostMapping
public Result addUser(@RequestBody User user) {
return Result.success(userService.addUser(user));
}
}3. 服务层实现(MyBatis Plus)
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public Page<User> pageQuery(int page, int limit) {
Page<User> pageQuery = new Page<>(page, limit);
return userMapper.selectPage(pageQuery, null);
}
public boolean addUser(User user) {
return userMapper.insert(user) > 0;
}
}五、完整案例
1. 数据库表结构
CREATE TABLE user (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);2. 完整项目结构
src
├── main
│ ├── java
│ │ └── com.example.ssm
│ │ ├── controller
│ │ │ └── UserController.java
│ │ ├── service
│ │ │ ├── UserService.java
│ │ │ └── impl
│ │ │ └── UserServiceImpl.java
│ │ └── mapper
│ │ └── UserMapper.java
│ └── resources
│ └── application.yml3. 完整前端页面(带分页)
<div class="layui-container">
<button class="layui-btn" id="addBtn">添加用户</button>
<table id="userTable" lay-filter="userTable"></table>
</div>
<script>
layui.use(['table', 'form', 'laypage'], function(){
var table = layui.table;
var laypage = layui.laypage;
var $ = layui.$;
var currentPage = 1;
var pageSize = 10;
// 查询接口
function queryUsers(page) {
$.ajax({
url: '/api/users',
type: 'GET',
data: {page: page, limit: pageSize},
success: function(res){
table.reload('userTable', {
page: {curr: page},
data: res.data
});
laypage.render({
elem: 'pageDiv',
count: res.total,
limit: pageSize,
curr: page,
layout: ['count', 'prev', 'page', 'next', 'limit'],
jump: function(obj, first){
if(!first){
queryUsers(obj.curr);
}
}
});
}
});
}
// 初始化表格
table.render({
elem: '#userTable',
url: '/api/users',
cols: [[
{type: 'checkbox'},
{field: 'id', title: 'ID'},
{field: 'name', title: '姓名'},
{field: 'email', title: '邮箱'}
]],
page: true
});
// 添加按钮事件
$('#addBtn').on('click', function(){
layer.open({
type: 1,
area: ['500px', '300px'],
content: '<div><input type="text" id="name" placeholder="姓名"><br>'+
'<input type="email" id="email" placeholder="邮箱"><br>'+
'<button id="submitBtn">提交</button></div>'
});
$('#submitBtn').on('click', function(){
$.ajax({
url: '/api/users',
type: 'POST',
data: {
name: $('#name').val(),
email: $('#email').val()
},
success: function(res){
layer.msg('添加成功');
queryUsers(1);
}
});
});
});
});
</script>六、源码解析
1. 分页参数传递
在前端通过URL参数传递分页信息:
data: {page: page, limit: pageSize}后端接收时使用:
@GetMapping
public Result queryUsers(@RequestParam int page, @RequestParam int limit)2. 数据格式处理
后端返回的JSON结构:
{
"code": 0,
"msg": "success",
"data": [
{"id": 1, "name": "张三", "email": "zhangsan@example.com"},
...
],
"total": 100
}3. 异常处理
在Controller中添加全局异常处理:
@ExceptionHandler
public Result handleException(Exception e) {
return Result.error("系统错误:" + e.getMessage());
}七、进阶使用
1. 复杂查询支持
通过layui的where参数支持条件查询:
layui.use('table', function(){
var table = layui.table;
table.render({
elem: '#userTable',
url: '/api/users',
where: { status: 1 }
});
});2. 分页优化
使用PageHelper插件实现分页:
@Auto
public class PageHelperConfig {
@Bean
public PageInterceptor pageInterceptor() {
return new PageInterceptor();
}
}3. 数据校验
使用Hibernate Validator进行参数校验:
public class User {
@NotNull(message = "姓名不能为空")
private String name;
@Email(message = "邮箱格式不正确")
private String email;
}八、性能与工程实践
1. 性能优化方案
启用MyBatis Plus的SQL日志:
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutLogger使用缓存减少数据库访问:
@Cacheable(value = "users", key = "#page + ':' + #limit") public Page<User> pageQuery(int page, int limit) { ... }
2. 安全风险分析
- SQL注入:使用预编译语句(MyBatis默认支持)
- 跨站攻击:配置CORS策略
- 数据篡改:使用HTTPS传输数据
3. 异常处理机制
- 前端使用try-catch捕获异常
后端统一返回错误码和错误信息
$.ajax({ url: '/api/users', type: 'POST', data: { ... }, error: function(xhr, status, error) { console.error('请求失败:', status, error); } });
九、常见问题与踩坑
1. 跨域问题
错误表现:浏览器控制台提示"Blocked by CORS policy"
解决办法:
- 后端配置CORS
- 使用代理服务器(如Nginx)
- 前端添加
withCredentials: false
2. 数据格式不匹配
错误表现:前端无法解析返回的JSON
解决办法:
- 确保返回JSON格式正确
- 使用
JSON.stringify()转换数据 - 检查Content-Type头是否为
application/json
3. 分页参数传递错误
错误表现:分页后数据不正确
解决办法:
- 确保前端传递的page参数从1开始
- 检查后端是否处理了分页参数
- 使用调试工具查看实际请求参数
十、最佳实践
1. 推荐方案
- 使用分页查询替代全量查询
- 对关键操作进行防重校验
- 使用异步加载提高响应速度
- 对敏感字段进行加密传输
2. 实施建议
- 前端使用layui的table组件进行数据展示
- 后端使用MyBatis Plus简化CRUD操作
- 对关键业务接口添加限流保护
- 对重要操作记录日志
十一、总结
通过本文的深入探讨,我们了解到在SSM项目中使用Ajax实现layui单表的查询和添加功能的完整方案。这种方案适用于需要频繁刷新数据但又不希望整个页面重载的场景,如数据看板、日志管理等。但需要注意以下几点:
适用场景:
- 需要动态更新数据的管理后台
- 需要提升用户体验的业务场景
- 需要快速开发的中小型项目
不适用场景:
- 需要处理大量实时数据的场景
- 需要复杂交互的前端应用
- 需要高度定制的UI组件
通过合理使用Ajax技术,结合layui的优秀组件,可以显著提升Web应用的性能和用户体验。同时,需要特别注意安全性、异常处理和性能优化等关键环节,确保系统的稳定性和可靠性。
评论已关闭