1,整合SSM:
A,整合SpringMVC和Spring:
a,SpringMVC的配置:
//扫描控制器与配置类所在的包
@ComponentScan({"top.jztice5.controller","top.jztice5.config"})
@EnableWebMvc
public class SpringMVCConfig {
}
package top.jztice5.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
* @author Jztice5
* @date 2022年03月29日 17:37
*/
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
/**
* 添加静态资源管理器组件
* 把静态资源放行
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
// System.out.println("启动静态资源放行...");
//添加所有静态资源文件夹,访问路径表示所有子孙目录都被映射,后面参数必须以*号结尾;
//放行静态资源;
// 当访问/pages/xxx时候,走/pages目录下的内容
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
/**
* 添加拦截器组件
*/
// @Override
// protected void addInterceptors(InterceptorRegistry registry) {
// // 配置注解拦截器和拦截控制器方法请求地址
// registry.addInterceptor(new BookInterceptor()).addPathPatterns("/books/**");
// }
}
b,Spring的配置:
//扫描service层的bean
@ComponentScan("top.jztice5.service")
//导入第三方bean
@Import({JdbcConfig.class,MyBatisConfig.class})
@EnableTransactionManagement //开启Spring的事务
public class SpringConfig {
}
c,* 整合SpringMVC和Spring的配置:
package top.jztice5.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* @author Jztice5
* @date 2022年03月29日 16:58
*/
//SpringMVC与Spring的配置类
@Configuration
public class ServletConfigInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//设置Spring核心配置
@Override
protected Class <?>[] getRootConfigClasses () {
return new Class[]{SpringConfig.class};
}
//设置MVC核心配置
@Override
protected Class <?>[] getServletConfigClasses () {
return new Class[]{SpringMVCConfig.class};
}
//设置拦截所有资源到webMVC
@Override
protected String[] getServletMappings () {
return new String[]{"/"};
}
}
B,整合Spring和MyBatis:
a,第三方bean配置类:
package top.jztice5.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.PropertySource;
import javax.sql.DataSource;
/**
* @author Jztice5
* @date 2022年03月29日 17:00
*/
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
//从jdbc.properties中读取键:jdbc.username,将它的值注入给username
@Value ("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driverClassName}")
private String driverClassName;
/**
* @Bean 注解的作用:
* 1. 用在方法上面
* 2. 将方法的返回对象,放到Spring的容器中,方法的名字就是对象的id
* 3. 也可以在Bean后面指定id的名字
* 4. 如果方法有参数,它会自动从Spring容器中去按类型匹配的方式查找,找到后注入
*/
@Bean
public DataSource dataSource(){
//创建druid数据源对象
DruidDataSource druidDataSource = new DruidDataSource();
//给数据源对象设置属性
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driverClassName);
//返回对象到容器
return druidDataSource;
}
}
package top.jztice5.config;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
/**
* @author Jztice5
* @date 2022年03月29日 17:03
*/
public class MyBatisConfig {
/**
* 创建会话工厂:
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean (DataSource dataSource) {
//创建会话工厂的bean对象
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//设置实体类路径别名:
sqlSessionFactoryBean.setTypeAliasesPackage("top.jztice5.pojo");
//设置会话对象数据源
sqlSessionFactoryBean.setDataSource(dataSource);
//创建配置对象
Configuration configuration = new Configuration();
//设置驼峰命名法
configuration.setMapUnderscoreToCamelCase(true);
//指定日志实现类,在控制台输出(显示)sql语句:
configuration.setLogImpl(StdOutImpl.class);
//建立配置对象与会话对象的联系:
sqlSessionFactoryBean.setConfiguration(configuration);
//返回第三方bean:会话对象到容器
return sqlSessionFactoryBean;
}
/**
* 1,扫描dao所在的包自动生成接口的实现类对象,并且返回放到Spring容器中
* 2. 扫描dao包下所有的xml配置文件和dao接口上注解,调用其中SQL语句
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
//创建映射扫描的配置对象
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置dao接口所在的包
mapperScannerConfigurer.setBasePackage("top.jztice5.dao");
//返回对象到容器中:
return mapperScannerConfigurer;
}
}
2,实现三层架构:
A,Web层:(Controller)
package top.jztice5.controller;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import top.jztice5.pojo.Book;
import top.jztice5.pojo.Code;
import top.jztice5.pojo.Result;
import top.jztice5.service.BookService;
import java.util.List;
/**
* @author Jztice5
* @date 2022年03月29日 16:56
*/
/**
* 控制器类用于调用业务层的实现类
*/
@RestController
@RequestMapping("/books")
public class BookController {
//注入业务层的bean
@Autowired
private BookService bookService;
//设置控制器方法类型
/**
* 查询所有
*/
@GetMapping
public Result setTextSelectAllBooks(){
List <Book> books = bookService.selectAllBook();
//设定返回的结果集
Integer code = books.size() > 0 ? Code.GET_OK :Code.GET_ERR;
String msg = books.size() > 0 ? "查询成功":"查询失败";
return new Result(books,code,msg);
}
/**
* 查询一个
* @param id
* @return
*/
//4种方式每种只能存在一个,当出现多个的时候要以路径进行区分;
@GetMapping("/{id}")
//get请求,用请求参数进行传递时记得加上:@PathVariable(在请求参数中获取数据)
public Result setSelectBook(@PathVariable Integer id){
Book book = bookService.selectBook(id);
Integer code = book != null ? Code.GET_OK :Code.GET_ERR;
String msg = book != null ? "查询成功":"查询失败";
return new Result(book,code,msg);
}
/**
* 添加数据
* @param book
* @return
*/
@PostMapping
public Result addBook(@RequestBody Book book){
int row = bookService.addBook(book);
//判断是否添加成功,将结构集的信息发送到前端,执行相应的弹窗策略
Integer code = row > 0 ? Code.SAVE_OK : Code.SAVE_ERR;
String msg = row > 0 ? "添加成功" : "添加失败";
return new Result(row,code, msg);
}
/**
* 修改数据
* @param book
* @return
*/
@PutMapping
public Result updateBook(@RequestBody Book book){
int row = bookService.UpdateBook(book);
Integer code = row > 0 ? Code.UPDATE_OK : Code.UPDATE_ERR;
String msg = row > 0 ? "修改成功":"修改失败";
return new Result(row,code,msg);
}
/**
* 删除数据
* @param id
* @return
*/
@DeleteMapping("/{id}")
public Result deleteBook(@PathVariable Integer id){
int row = bookService.deleteBook(id);
Integer code = row > 0 ? Code.DELETE_OK : Code.DELETE_ERR;
String msg = row > 0 ? "删除成功":"删除失败";
return new Result(row,code,msg);
}
}
@RestController = @Controller+@ResponseBody ;(但是该注解不能用于JSP);
B,Service层:
- **Service层接口的实现类:**
package top.jztice5.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.jztice5.dao.BookDao;
import top.jztice5.pojo.Book;
import top.jztice5.service.BookService;
import java.util.List;
/**
* @author Jztice5
* @date 2022年03月29日 17:11
*/
@Service("bookServiceImpl")
public class BookServiceImpl implements BookService {
//注入bean对象
@Autowired
private BookDao bookDao;
@Override
public List <Book> selectAllBook () {
return bookDao.selectAllBook();
}
@Override
public Book selectBook (Integer id) {
return bookDao.findBook(id);
}
@Override
public int addBook (Book book) {
return bookDao.save(book);
}
@Override
public int UpdateBook (Book book) {
return bookDao.UpdateBook(book);
}
@Override
public int deleteBook (Integer id) {
return bookDao.delete(id);
}
}
- **Service的接口:**
package top.jztice5.service;
/**
* @author Jztice5
* @date 2022年03月29日 17:11
*/
import top.jztice5.pojo.Book;
import java.util.List;
/**
* 业务层接口其实是一种约束,在接口中写上要实现的方法,以避免漏写需要的需求
*/
public interface BookService {
/**
* 查询所有数据;
* @return list of books
*/
List<Book> selectAllBook();
/**
* 查询一条数据
* @param id
* @return
*/
Book selectBook(Integer id);
/**
* 添加一条数据
* @param book
* @return
*/
int addBook(Book book);
/**
* 修改数据
* @param book
* @return
*/
int UpdateBook(Book book);
/**
* 删除数据
* @param id
* @return
*/
int deleteBook(Integer id);
}
C,DAO层:
package top.jztice5.dao;
/**
* @author Jztice5
* @date 2022年03月29日 17:11
*/
import org.apache.ibatis.annotations.*;
import top.jztice5.pojo.Book;
import java.util.List;
/**
* dao层接口用于被业务层实现类调用
*/
public interface BookDao {
/**
* 查询所有
* @return
*/
@Select("select * from spring_db.tbl_book")
List<Book> selectAllBook();
/**
* 查询一个数据
* @param id
* @return
*/
@Select("select * from spring_db.tbl_book where id=#{id}")
Book findBook(Integer id);
/**
* 添加数据
* @param book
* @return
*/
@Insert("insert into spring_db.tbl_book values (null,#{type},#{name},#{description})")
int save(Book book);
/**
* 修改数据
* @param book
* @return
*/
@Update("update spring_db.tbl_book set type=#{type},name=#{name},description=#{description} where id=#{id}")
int UpdateBook(Book book);
/**
* 删除数据
* @param id
* @return
*/
@Delete("delete from spring_db.tbl_book where id=#{id}")
int delete( Integer id);
}
3,设置实体类与前端数据结果集:
A,实体类:
package top.jztice5.pojo;
import lombok.Data;
/**
* @author Jztice5
* @date 2022年03月29日 17:10
*/
@Data
public class Book {
private Integer id;
private String type; //书籍类型
private String name; //书名
private String description; //描述
}
B,通知结果集:
- 结果集的实体类:
package top.jztice5.pojo;
import lombok.Data;
/**
* @author Jztice5
* @date 2022年03月29日 18:22
*/
/**
* 定义结果集
*/
@Data
public class Result {
private Object data; //服务器返回数据
private Integer code; //返回操作码
private String msg; //返回操作信息
//为了操作方便,添加更多的构造方法
public Result() {
}
public Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Result(Object data, Integer code) {
this.data = data;
this.code = code;
}
public Result(Object data, Integer code, String msg) {
this.data = data;
this.code = code;
this.msg = msg;
}
}
- 状态码接口
package top.jztice5.pojo;
/**
* @author Jztice5
* @date 2022年03月29日 18:21
*/
public interface Code {
Integer SAVE_OK = 20011;
Integer DELETE_OK = 20021;
Integer UPDATE_OK = 20031;
Integer GET_OK = 20041;
Integer SAVE_ERR = 20010;
Integer DELETE_ERR = 20020;
Integer UPDATE_ERR = 20030;
Integer GET_ERR = 20040;
Integer SYSTEM_ERR = 50001;
Integer SYSTEM_TIMEOUT_ERR = 50002;
Integer SYSTEM_UNKNOWN_ERR = 59999;
Integer BUSINESS_ERR = 60002;
}
4,前端静态页面代码:
<!DOCTYPE html>
<html>
<head>
<!-- 页面meta -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>SpringMVC案例</title>
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
<!-- 引入样式 -->
<link rel="stylesheet" href="../plugins/elementui/index.css">
<link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="../css/style.css">
</head>
<body class="hold-transition">
<div id="app">
<div class="content-header">
<h1>图书管理</h1>
</div>
<div class="app-container">
<div class="box">
<div class="filter-container">
<el-input placeholder="图书名称" v-model="pagination.queryString" style="width: 200px;"
class="filter-item"></el-input>
<el-button @click="getAll()" class="dalfBut">查询</el-button>
<el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
</div>
<el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row>
<el-table-column type="index" align="center" label="序号"></el-table-column>
<el-table-column prop="type" label="图书类别" align="center"></el-table-column>
<el-table-column prop="name" label="图书名称"></el-table-column>
<el-table-column prop="description" label="描述"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增标签弹层 -->
<div class="add-form">
<el-dialog title="新增图书" :visible.sync="dialogFormVisible">
<el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right"
label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="handleAdd()">确定</el-button>
</div>
</el-dialog>
</div>
<!-- 编辑标签弹层 -->
<div class="add-form">
<el-dialog title="编辑检查项" :visible.sync="dialogFormVisible4Edit">
<el-form ref="dataEditForm" :model="formData" :rules="rules" label-position="right"
label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible4Edit = false">取消</el-button>
<el-button type="primary" @click="handleEdit()">确定</el-button>
</div>
</el-dialog>
</div>
</div>
</div>
</div>
</body>
<!-- 引入组件库 -->
<script src="../js/vue.js"></script>
<script src="../plugins/elementui/index.js"></script>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script src="../js/axios-0.18.0.js"></script>
<script>
var vue = new Vue({
el: '#app',
data: {
pagination: {},
dataList: [],//当前页要展示的列表数据
formData: {},//表单数据
dialogFormVisible: false,//控制表单是否可见
dialogFormVisible4Edit: false,//编辑表单是否可见
rules: {//校验规则
type: [{required: true, message: '图书类别为必填项', trigger: 'blur'}],
name: [{required: true, message: '图书名称为必填项', trigger: 'blur'}]
}
},
//钩子函数,VUE对象初始化完成后自动执行
created() {
this.getAll();
},
methods: {
//列表
getAll() {
axios.get("/books").then(resp => {
let result = resp.data;
//表示查询成功
if (result.code == 20041) {
this.dataList = result.data;
}
});
},
//弹出添加窗口
handleCreate() {
this.dialogFormVisible = true;
this.resetForm();
},
//重置表单
resetForm() {
this.formData = {};
},
//添加
handleAdd() {
axios.post("/books", this.formData).then(resp => {
let result = resp.data;
if (result.code === 20011) {
this.$message.success("添加成功");
} else {
this.$message.error("添加失败");
}
}).finally(resp => {
//无论结果如何都进行创新数据列表;
this.dialogFormVisible = false;
this.getAll();
})
},
//弹出编辑窗口
handleUpdate(row) {
axios.get("/books/" + row.id).then(resp => {
let result = resp.data;
if (result.code == 20041) {
//将数据显示在表单上
this.formData = result.data;
//展示弹层,加载数据,不是添加对话框
this.dialogFormVisible4Edit = true;
}
});
},
//编辑
handleEdit() {
//发送ajax请求
axios.put("/books",this.formData).then(resp => {
let result = resp.data;
if (result.code == 20031) {
//如果操作成功
this.$message.success(result.msg);
//关闭弹层,显示数据
this.dialogFormVisible4Edit = false;
}
}).finally(resp=>{
//无论添加成功还是失败都再次获取数据
this.getAll();
});
},
// 删除
handleDelete(row) {
//1.弹出提示框
this.$confirm('真的要删除这本书吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//2.做删除业务
axios.delete("/books/" + row.id).then(resp => {
let result = resp.data;
if (result.code == 20021) {
this.$message({
type: 'success',
message: '删除成功!'
});
}
}).finally(resp => {
//无论添加成功还是失败都再次获取数据
this.getAll();
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
}
})
</script>
</html>
* 要导入的依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>top.jztice5</groupId>
<artifactId>SSM-project-A</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- 导入springmvc的包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.11.RELEASE</version>
</dependency>
<!-- 添加json相关的依赖,如JSON转Java-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
</project>