父工程中依赖(pom.xml)
<dependencies>
<!--springcontext-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.14</version>
</dependency>
<!--spring-tx-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>6.1.14</version>
</dependency>
<!--spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.1.14</version>
</dependency>
<!--aspectj-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.21</version>
</dependency>
<!--jsr250注解-->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.1.14</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
</dependency>
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
</dependency>
<!--hibernate-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>6.1.0</version>
</dependency>
<!--spring-web-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.1.14</version>
</dependency>
<!--spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.3</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.23</version>
</dependency>
<!--logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.12</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
</dependency>
</dependencies>
配置文件(config)
此处采用全注解开发,用java类的方式进行配置,并按照三层架构,框架整合的方式将所有配置拆分成5个配置类。这5个配置类又分别用于两个IoC容器,一个专门负责处理web请求(web容器),另一个负责处理后端数据(root容器),前者作为后者的子容器,使得可以在处理前端请求的时候调用后端service层等的方法
Web容器配置文件
webMvcJavaConfig
package com.atli.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
/**
* @ClassName:WebMvcJavaConfig
* @Author: hasee
* @Date: 2024.12.26 17:10
* @Description:
*/
// 配置类
@Configuration
// 配置包扫描
@ComponentScan({"com.atli.controller","com.atli.exceptionhandler"})
// 自动添加handlerMapping,handlerAdapter
@EnableWebMvc
public class WebMvcJavaConfig implements WebMvcConfigurer {
// 静态资源处理
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
// 视图解析器
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/jsp/", ".jsp");
}
// 拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
}
Root容器配置文件
ServiceJavaConfig
package com.atli.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
* @ClassName:ServiceJavaConfig
* @Author: hasee
* @Date: 2024.12.26 17:25
* @Description:
*/
// 配置类
@Configuration
// 包扫描
@ComponentScan("com.atli.service")
// 开启aspectj注解支持
@EnableAspectJAutoProxy
// 开启事务注解支持
@EnableTransactionManagement
public class ServiceJavaConfig {
// 事务管理器实现
@Bean
public TransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
MapperJavaConfig
package com.atli.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
import java.util.Properties;
/**
* @ClassName:MapperJavaConfig
* @Author: hasee
* @Date: 2024.12.26 17:35
* @Description:
*/
// 配置类
@Configuration
public class MapperJavaConfig {
// 利用mybatis提供的SqlSessionFactoryBean配置SqlSessionFactory
// 千万注意,是mybatis提供的,如果要使用mybatisplus则需要用其他的工厂对象MybatisSqlSessionFactoryBean
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 配置数据源
sqlSessionFactoryBean.setDataSource(dataSource);
// 指定mybatis配置文件功能
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//开启驼峰映射
configuration.setMapUnderscoreToCamelCase(true);
// 开启logback
configuration.setLogImpl(Slf4jImpl.class);
// 开启resultMap自动映射
configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
// 启用configuration实例中配置
sqlSessionFactoryBean.setConfiguration(configuration);
// 设置别名
sqlSessionFactoryBean.setTypeAliasesPackage("com.atli.pojo");
// 添加pagehelper插件
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "mysql");
pageInterceptor.setProperties(properties);
sqlSessionFactoryBean.addPlugins(pageInterceptor);
return sqlSessionFactoryBean;
}
// mapper代理对象
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
// 设置mapper接口与xml文件所在共同包
mapperScannerConfigurer.setBasePackage("com.atli.mapper");
return mapperScannerConfigurer;
}
}
DataSourceJavaConfig
package com.atli.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
/**
* @ClassName:DataSouceJavaConfig
* @Author: hasee
* @Date: 2024.12.26 18:53
* @Description: 若将配置datasouce和mapper放一个配置类中会因为加载顺序问题使得数据库连接信息为空
*/
@Configuration
// 导入配置文件
@PropertySource("classpath:jdbc.properties")
public class DataSourceJavaConfig {
// 导入数据库连接信息
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driver;
// 配置数据源
@Bean
public DataSource dataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(password);
return ds;
}
}
IoC整合配置
SpringIoCInit
package com.atli.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* @ClassName:SpringIoCInit
* @Author: hasee
* @Date: 2024.12.26 19:16
* @Description:
*/
@Configuration
public class SpringIoCInit extends AbstractAnnotationConfigDispatcherServletInitializer {
// rootioc容器配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ServiceJavaConfig.class, DataSourceJavaConfig.class, MapperJavaConfig.class};
}
// webioc容器配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebMvcJavaConfig.class};
}
// dispatcherServlet拦截路径
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
实体类(pojo)
Customer
package com.atli.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Data;
/**
* @TableName customer
*/
@TableName(value ="customer")
@Data
public class Customer {
private Integer id;
private String userName;
private Integer capital;
}
CustomerPageResult
package com.atli.pojo;
import lombok.Data;
import java.util.List;
/**
* @ClassName:CustomerPageResut
* @Author: hasee
* @Date: 2024.12.29 14:48
* @Description:用于包装分页查询结果
*/
@Data
public class CustomerPageResult {
Integer currentPage;
Integer pageSize;
long totalRecords;
List<Customer> customers;
}
控制层(controller)
package com.atli.controller;
import com.atli.pojo.Customer;
import com.atli.pojo.CustomerPageResult;
import com.atli.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @ClassName:CustomerController
* @Author: hasee
* @Date: 2024.12.26 20:24
* @Description:
*
* todo:api: ssm/
* get "/customer/{currentPage}/{pageSize}"
* selectAllCustomers() 查询所有信息并按照页码,页面大小返回
* get "/customer/{id}"
* selectCustomerById() 根据id查询单个用户并返回
* post "/customer"
* insertCustomer() 新增用户
* delete "/customer/{id}"
* deleteCustomer() 删除用户
* put "/customer"
* updateCustomer() 修改用户
*/
@RestController
public class CustomerController {
@Autowired
private CustomerService customerService;
@GetMapping("/customer/{currentPage}/{pageSize}")
public CustomerPageResult selectAllCustomers(@PathVariable("currentPage") Integer currentPage, @PathVariable("pageSize") Integer pageSize) {
return customerService.selectAllaCustomer(currentPage,pageSize);
}
@GetMapping("/customer/{id}")
public Customer selectCustomerById(@PathVariable("id") Integer id) {
return customerService.selectCustomerById(id);
}
@PostMapping("/customer")
public int insertCustomer(@RequestBody Customer customer) {
return customerService.insertCustomer(customer);
}
@DeleteMapping("/customer/{id}")
public int deleteCustomer(@PathVariable("id") Integer id) {
return customerService.deleteCustomer(id);
}
@PutMapping("/customer")
public int updateCustomer(@RequestBody Customer customer) {
return customerService.updateCustomer(customer);
}
}
业务层(service)
接口
CustomerService
package com.atli.service;
import com.atli.pojo.Customer;
import com.atli.pojo.CustomerPageResult;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* @author hasee
* @description 针对表【customer】的数据库操作Service
* @createDate 2024-12-26 19:35:01
*/
public interface CustomerService extends IService<Customer> {
CustomerPageResult selectAllaCustomer(Integer currentPage, Integer pageSize);
Customer selectCustomerById(Integer id);
int insertCustomer(Customer customer);
int deleteCustomer(Integer id);
int updateCustomer(Customer customer);
}
实体类
CustomerServiceImpl
package com.atli.service.impl;
import com.atli.pojo.CustomerPageResult;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atli.pojo.Customer;
import com.atli.service.CustomerService;
import com.atli.mapper.CustomerMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author hasee
* @description 针对表【customer】的数据库操作Service实现
* @createDate 2024-12-26 19:35:01
*/
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer>
implements CustomerService{
@Autowired
private CustomerMapper customerMapper;
@Override
public CustomerPageResult selectAllaCustomer(Integer currentPage, Integer pageSize) {
PageHelper.startPage(currentPage, pageSize);
// 全体结果集
List<Customer> all = customerMapper.selectAllCustomer();
// 封装成pageInfo对象
PageInfo<Customer> pageInfo = new PageInfo<>(all);
// 创建查询结果集
CustomerPageResult customerPageResult = new CustomerPageResult();
// 赋值查询结果
customerPageResult.setCustomers(pageInfo.getList());
// 赋值当前页码
customerPageResult.setCurrentPage(pageInfo.getPageNum());
// 赋值单页信息条数
customerPageResult.setPageSize(pageInfo.getPageSize());
// 赋值总计条数
customerPageResult.setTotalRecords(pageInfo.getTotal());
return customerPageResult;
}
@Override
public Customer selectCustomerById(Integer id) {
return customerMapper.selectCustomerById(id);
}
@Override
public int insertCustomer(Customer customer) {
return customerMapper.insertCustomer(customer);
}
@Override
public int deleteCustomer(Integer id) {
return customerMapper.deleteCustomer(id);
}
@Override
public int updateCustomer(Customer customer) {
return customerMapper.updateCustomer(customer);
}
}
持久层(mapper)
mapper接口
package com.atli.mapper;
import com.atli.pojo.Customer;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author hasee
* @description 针对表【customer】的数据库操作Mapper
* @createDate 2024-12-26 19:35:01
* @Entity com.atli.pojo.Customer
*/
@Mapper
public interface CustomerMapper extends BaseMapper<Customer> {
List<Customer> selectAllCustomer();
Customer selectCustomerById(Integer id);
int insertCustomer(Customer customer);
int deleteCustomer(Integer id);
int updateCustomer(Customer customer);
}
mapper映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atli.mapper.CustomerMapper">
<resultMap id="BaseResultMap" type="com.atli.pojo.Customer">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
<result property="capital" column="capital" jdbcType="INTEGER"/>
</resultMap>
<insert id="insertCustomer" >
insert into Customer(user_name,capital) values (#{userName},#{capital})
</insert>
<update id="updateCustomer">
update customer set user_name=#{userName} , capital=#{capital} where id=#{id}
</update>
<delete id="deleteCustomer">
delete from customer where id=#{id}
</delete>
<select id="selectAllCustomer" resultType="com.atli.pojo.Customer">
select * from Customer
</select>
<select id="selectCustomerById" resultType="com.atli.pojo.Customer">
select * from Customer where id=#{id}
</select>
</mapper>
前端(vue+vite)
安装axios,element-plus
配置全局element-plus
main.js
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
配置proxy代理服务器
vite.config.js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
// 跨域
server: {
proxy: {
'/ssm':{
target: 'http://127.0.0.1:8080',
}
}
},
})
App.vue
<script setup>
import {ref, onMounted, reactive, isRef} from 'vue'
import axios from "axios";
// 保存查询所有客户数据
let customers = ref([]);
// 判断修改框是否展示
let editFormVisible = ref(false)
// 判断添加框是否展示
let addFormVisible = ref(false)
// 客户对象
const customer = reactive({
id:0,
userName:'',
capital:0,
})
// 存储查询条件
const search = ref();
// 数据页面大小
const pageSize = ref(5);
// 总页数
const totalRecords = ref(1);
// 当前页码
const currentPage = ref(1);
// 当前分页对象
const customerPageResult = reactive({
currentPage: 1,
pageSize: pageSize,
totalRecords: totalRecords,
customers: customers,
})
// 页面挂载时触发查询所有信息操作
onMounted(async () => {
await getAllCustomers();
})
// 点击修改按钮
function editFormOpen(index, row){
customer.id=row.id;
editFormVisible.value = true;
}
// 提交修改
function editFormClose(){
editFormVisible.value = false;
handleEdit(customer);
}
// 点击添加按钮
function addFormOpen(){
addFormVisible.value = true;
}
// 提交添加
function addFormClose(){
addFormVisible.value = false;
handleAdd(customer);
}
// 页面变动
function handleCurrentChange(){
getAllCustomers();
}
/*
* 获取所有用户 get:/ssm/customer
* 根据id获取用户 get:/ssm/customer/id
* 新增用户 post:/ssm/customer 请求体携带对象
* 删除用户 delete:/ssm/customer/id
* 修改用户 put:/ssm/customer 请求体携带对象*/
// 新增用户
async function handleAdd(customer) {
const response = await axios.post('/ssm/customer', customer).then(
async () => await getAllCustomers()
);
customer.id=0;
customer.userName="";
customer.capital=0;
}
// 删除用户
async function handleDelete(index, row) {
const response = await axios.delete('/ssm/customer/'+row.id).then(
async () => await getAllCustomers()
);
customer.id=0;
customer.userName="";
customer.capital=0;
}
// 修改用户
async function handleEdit(customer) {
const response = await axios.put('/ssm/customer',customer).then(
async () => await getAllCustomers()
);
customer.id=0;
customer.userName="";
customer.capital=0;
}
// 查询所有用户
async function getAllCustomers() {
// 千万记住ref要用.value取值
const response = await axios.get('/ssm/customer/'+currentPage.value+'/'+pageSize.value);
customers.value = response.data.customers;
currentPage.value = response.data.currentPage;
pageSize.value = response.data.pageSize;
totalRecords.value = response.data.totalRecords;
console.log();
}
// 根据id查询单个用户
async function getCustomerById(id) {
if(id){
const response = await axios.get('/ssm/customer/'+id)
customers.value = [response.data];
}else {
await getAllCustomers();
}
}
</script>
<template>
<div class="common-layout">
<el-container>
<!-- 包含新增和查询的上方栏 -->
<el-header height="auto">
<el-row :gutter="18">
<el-col :span="16"><el-button type="primary" @click="addFormOpen" >新增顾客</el-button></el-col>
<el-col :span="4">
<el-input type="text" placeholder="请输入查询id" style="width:300px" v-model="search" clearable @change="getCustomerById" />
</el-col>
</el-row>
</el-header>
<!-- 展示数据 -->
<el-main>
<el-table :data="customers" height="auto" style="width: 100%">
<el-table-column prop="id" label="id" width="180" />
<el-table-column prop="userName" label="姓名" width="180" />
<el-table-column prop="capital" label="余额" />
<el-table-column label="Operations">
<template #default="scope">
<el-button size="small" @click="editFormOpen(scope.$index, scope.row)">
Edit
</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>
Delete
</el-button>
<!-- 编辑用户框 -->
<el-dialog v-model="editFormVisible" title="编辑用户" width="500">
<el-form :model="customer" :inline="true">
<el-form-item label="id" :label-width="100">
<el-input disabled v-model="customer.id"/>
</el-form-item>
<el-form-item label="姓名" :label-width="100">
<el-input v-model="customer.userName"/>
</el-form-item>
<el-form-item label="余额" :label-width="100">
<el-input v-model="customer.capital"/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="editFormVisible = false">Cancel</el-button>
<el-button type="primary" @click="editFormClose">
Confirm
</el-button>
</div>
</template>
</el-dialog>
<!-- 新增用户框 -->
<el-dialog v-model="addFormVisible" title="新增用户" width="500">
<el-form :model="customer" :inline="true">
<el-form-item label="姓名" :label-width="100">
<el-input v-model="customer.userName"/>
</el-form-item>
<el-form-item label="余额" :label-width="100">
<el-input v-model="customer.capital"/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="editFormVisible = false">Cancel</el-button>
<el-button type="primary" @click=addFormClose>
Confirm
</el-button>
</div>
</template>
</el-dialog>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 40px">
<el-pagination
v-model:current-page="currentPage"
:page-size=pageSize
:disabled="false"
:background="true"
layout="total, prev, pager, next"
:total=totalRecords
@current-change="handleCurrentChange"
/>
</div>
</el-main>
</el-container>
</div>
</template>
<style scoped>
</style>