目录
后端相关代码
Controller层
@PostMapping
public AjaxResult selectProduct(@RequestParam(defaultValue = "1")int pageNum, @RequestParam(defaultValue = "5")int pageSize, @RequestBody(required = false)ProductDTO productDTO){
return AjaxResult.success(productService.selectProduct(pageNum,pageSize,productDTO));
}
Service层
@Override
public IPage<Product> selectProduct(int pageNum, int pageSize, @Param("productDTO")ProductDTO productDTO) {
Page<Product> page = new Page<>(pageNum, pageSize);
// 非空判断
if (productDTO == null) {
productDTO = new ProductDTO();
}
page.setCurrent(pageNum);
return productMapper.selectProduct(page,productDTO);
}
Mapper层
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
IPage<Product> selectProduct(IPage<Product> page, @Param("productDTO")ProductDTO productDTO);
}
Mapper.xml
<select id="selectProduct" resultType="com.zhan.springboot.springbootmybatis.pojo.Product">
select *
from springboot.product
<where>
<if test="productDTO.pid != null and productDTO.pid != ''">pid=#{productDTO.pid}</if>
<if test="productDTO.pname != null and productDTO.pname != ''">And pname=#{productDTO.pname}</if>
<if test="productDTO.price != null and productDTO.price != ''">And price=#{productDTO.price}</if>
</where>
</select>
Product
@AllArgsConstructor
@NoArgsConstructor
public class Product implements Serializable {
private Integer pid;
private String pname;
private Double price;
@TableField(value = "category_id")
private String categoryId;
private static final long serialVersionUID = 1L;
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname == null ? null : pname.trim();
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getCategoryId() {
return categoryId;
}
public void setCategoryId(String categoryId) {
this.categoryId = categoryId == null ? null : categoryId.trim();
}
}
以上要求有相关数据库,sql语句如下:
-- auto-generated definition
create table product
(
pid int auto_increment
primary key,
pname varchar(20) not null,
price double null,
category_id varchar(20) null
);
前端相关代码
基于Element-ui和axios
<template>
<div>
<el-table :data="productList" border>
<el-table-column prop="pid" label="Product ID"></el-table-column>
<el-table-column prop="pname" label="Product Name"></el-table-column>
<el-table-column prop="price" label="Price"></el-table-column>
<el-table-column prop="categoryId" label="Category ID"></el-table-column>
</el-table>
<el-pagination @size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page-sync="currentPage"
:page-size="pageSize" layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
productList: [],
pageNum: 1,
pageSize: 10,
total: null
};
},
created() {
this.fetchProductList();
},
methods: {
fetchProductList() {
const params = {
pageNum: this.pageNum,
pageSize: this.pageSize
};
axios.post(`http://localhost:8080/product?pageNum=${params.pageNum}&pageSize=${params.pageSize}`)
.then(response => {
this.productList = response.data.records;
this.total = response.data.total;
})
.catch(error => {
console.error('Error fetching product list:', error);
});
},
// 分页处理方法
handleSizeChange(val) {
this.pageSize = val;
this.fetchProductList();
console.log(`每页 ${val} 条`);
},
//改变当前下标页的时触发,再调一遍接口
handleCurrentChange(val) {
this.pageNum = val;
this.fetchProductList();
console.log(`当前页: ${val}`);
//主要 axios
}
}
};
</script>
注意这边要在main.js添加响应拦截:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import 'element-ui/lib/theme-chalk/index.css';
import ElementUI from "element-ui";
import axios from "axios";
Vue.config.productionTip = false;
Vue.prototype.$axios = axios;
Vue.use(ElementUI);
//------------------请求拦截-------------------//
axios.interceptors.request.use(config => {
//例:若存在token则带token
const token = store.state.token;
if (token) {
config.headers.Authorization = token
}
return config;
}, err => {
console.log("请求拦截=>", err);
return err;
})
//------------------响应拦截-------------------//
//-------------对响应数据做点什么-------------//
axios.interceptors.response.use(res => {
console.log("响应拦截=>", res.data);
//例:后端数据处理错误,并返回错误原因;前端获取错误原因并展示
if (res.data.success == false) {
Message({
message: res.data.data.message + ',请重试!',
type: 'warning'
});
}
console.log("响应拦截=>", res);
return res ? res.data : res;
}, err => {
console.log(err);
//打印完整的错误信息
console.log("响应拦截错误完整信息=>",err.response)
//也可以在这里对不同的错误码做不同的展示处理
throw err;
})
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
上面我没有作条件查询,因此没有传ProductDTO进去,相当于无条件查询,会列出所有的数据列表:
关键的请求代码是:
axios.post(`http://localhost:8080/product?pageNum=${params.pageNum}&pageSize=${params.pageSize}`)
params是请求体参数,如下定义:
const params = {
pageNum: this.pageNum,
pageSize: this.pageSize
};
当然加上条件查询的话,你还得加上一个VTO:
const productDTO = {
// 根据需要设置其他的查询条件
};
这边要注意一个地方:设置请求头: 在发送请求时,确保设置适当的请求头,特别是Content-Type
头,以指示后端请求体的格式。对于JSON格式的请求体,通常使用Content-Type: application/json
。
当然 如果每次请求都声明header未免太过麻烦,我们可以在main.js中设置,即作请求拦截器,整个代码示例如下:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import 'element-ui/lib/theme-chalk/index.css';
import ElementUI from "element-ui";
import axios from "axios";
Vue.config.productionTip = false;
Vue.prototype.$axios = axios;
Vue.use(ElementUI);
//------------------请求拦截-------------------//
axios.interceptors.request.use(config => {
//例:若存在token则带token
const token = store.state.token;
config.headers['Content-Type'] = 'application/json';//这边声明了请求头类型
if (token) {
config.headers.Authorization = token
}
return config;
}, err => {
console.log("请求拦截=>", err);
return err;
})
//------------------响应拦截-------------------//
//-------------对响应数据做点什么-------------//
axios.interceptors.response.use(res => {
console.log("响应拦截=>", res.data);
//例:后端数据处理错误,并返回错误原因;前端获取错误原因并展示
if (res.data.success == false) {
Message({
message: res.data.data.message + ',请重试!',
type: 'warning'
});
}
console.log("响应拦截=>", res);
return res ? res.data : res;
}, err => {
console.log(err);
//打印完整的错误信息
console.log("响应拦截错误完整信息=>",err.response)
//也可以在这里对不同的错误码做不同的展示处理
throw err;
})
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
效果
前端设置了选择pagesize大小的功能:
至此,一个最简单的前后端对接的例子完成,后续根据自己的需求拓展,例如文件上传、登录校验功能或增加条件查询的功能等