SpringBoot 基础学习
对于SpringBoot的了解,在初学者的角度看来,它是一种工具,用于简化一个Spring项目的初始搭建和开发过程。
1 入门案例
1.1 项目的创建
有四种方法创建,可以通过idea快捷创建,Spring的官网创建,阿里云创建,以及手动创建。(这里以idea的方式来创建)
(1)文件 -> 新建项目
输入项目名称,选择Spring initializr的生成器。项目类型选择Maven类型。
(2)勾选所需要的依赖和配置
选择好点击创建,成功创建一个Spring Boot的项目
项目创建好以后的结构和部分xml配置信息
1.2 Controller 的书写
package com.example.studaydemo_1.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.Controller;
@Controller
@RequestMapping("/Users")
public class UserController {
@GetMapping
public String getUser(){
System.out.println("helloWord");
return "Hello World";
}
}
1.3 运行项目
项目成功运行界面 发现启动了Tomcat服务器并提供了端口8080以供访问
网页显示访问信息
入门案例
package com.example.studaydemo_1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/Users")
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("save running...");
return "save running...";
}
@RequestMapping("/update")
@ResponseBody
public String update(){
System.out.println("update running...");
return "update running...";
}
@RequestMapping("/delete")
@ResponseBody
public String delete(){
System.out.println("delete running...");
return "delete running...";
}
@RequestMapping("/findAll")
@ResponseBody
public String findAll(){
System.out.println("findAll running...");
return "findAll running...";
}
@RequestMapping("/findById")
@ResponseBody
public String findById(){
System.out.println("findById running...");
return "findById running...";
}
}
2 REST风格
表现形式状态转换 对于资源的描述形式
传统资源描述形式
http:/localhost/user/getById?id=1
http://localhost/user/saveUser
Rest风格描述形式
http://localhost/users/1
http://localhost/user
根据rest风格进行访问称作Restful
优点:
- 书写简洁
- 隐藏资源的访问形式
2.1 Rest风格转换
设定http请求动作(动词)
设定请求参数(路径变量)
package com.example.studaydemo_1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class UserController_2 {
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save(){
System.out.println("save running...");
return "save running...";
}
@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(){
System.out.println("update running...");
return "update running...";
}
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable String id){
System.out.println("delete"+ id +" running...");
return "delete running...";
}
@RequestMapping(value = "/users",method = RequestMethod.GET)
@ResponseBody
public String findAll(){
System.out.println("findAll running...");
return "findAll running...";
}
}
@RequestMapping
类型: 方法注解
位置:SpringMVC控制器定义上方
作用:设置当前控制器方法的请求访问路径
范例:
@RequestMapping(value = "/users",method = RequestMethod.POST) @ResponseBody public String save(){ System.out.println("save running..."); return "save running..."; }
属性:
value:方法请求访问路径
method:http请求动作,标准动作(GET PUT DELETE)
@PathVariable
类型:形参注解
位置:SpringMVC形参定义的前面
作用:绑定路径参数和方法形参间的关系,要求路径参数名和形参名一一对应
范例:
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE) @ResponseBody public String delete(@PathVariable String id){ System.out.println("delete"+ id +" running..."); return "delete running..."; }
2.2 RESTful快速开发
继续简化上述的内容,提取共同的部分来简化代码,以实现快速开发
package com.example.studaydemo_1.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
public class UserController {
// @RequestMapping(method = RequestMethod.POST)
@PostMapping
public String save(){
System.out.println("save running...");
return "save running...";
}
// @RequestMapping(method = RequestMethod.PUT)
@PutMapping
public String update(){
System.out.println("update running...");
return "update running...";
}
// @RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
@DeleteMapping("/id")
public String delete(@PathVariable String id){
System.out.println("delete"+ id +" running...");
return "delete running...";
}
//@RequestMapping(method = RequestMethod.GET)
@GetMapping
public String findAll(){
System.out.println("findAll running...");
return "findAll running...";
}
}
3 属性配置
不同配置文件中相同配置按照加载优先级相互覆盖,不同文件中不同配置全部保留
3.1 properpties配置
SpringBoot的默认配置文件,使用键值对配置对应属性
# 服务器配置
server.port = 80
# 修改banner
# 自动分析图片
spring.banner.location = text.png
# 配置日志级别
# debug info(信息)[默认] error(错误) warn
logging.level.root = info
3.2 yml配置
配置文件的主流形式
# 服务器器配置
server:
port: 8080
3.3 yaml配置
一种数据序列化格式
优点:容易阅读 容易与脚本语言交互 以数据为核心 重数据轻格式
文件扩展名:.yml .yaml
yaml语法规则
- 大小写敏感
- 属性缩进表示层级关系,每行结束使用冒号结束
- 用层级左侧对齐,只允许使用空格
- 属性值前面加空格(属性名和属性值之间使用冒号+空格作为分隔)
- #表示注释
country : china
city: taiyuan
name: zhangsan
age: 18
user:
name: zhangsan
age: 18
class_id:
- class1
- class2
- class3
class_2: [class1,class2,class3]
class_1:
-
name: 1
number: 50
-
name: 2
number: 60
class_3: [{name: 3, number: 70},{name: 4, number: 80},class3]
yaml配置文件属性 数组 对象的书写形式
数据读取
package com.example.studaydemo_1.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/users")
public class UserController_2 {
// 读取yaml配置文件
@Value("${country}")
private String country;
@Value("${user.age}")
private String age;
@Value("${class_id[0]}")
private String class1;
@Value("${class_1[0].number}")
private String number;
@GetMapping
public String getInfo(){
System.out.println("country===>"+country);
System.out.println("number===>"+age);
System.out.println("class===>"+class1);
System.out.println("number===>"+number);
return "INFO:" + country + ":" + age + ":" + class1;
}
}
1. 可以使用${属性名}的方式来调用数据
# 以使用${属性名}的方式来调用数据
baseDir: D:\test
tempDir: ${baseDir}\temp
# 字符中的转义字符可以正常使用
testDir: "${baseDir} \t1\t2\t3}"
2. 自动装配
// 自动装配对象 数据全部封装到env对象中
@Autowired
private Environment env;
@GetMapping
public String getInfo(){
System.out.println("country===>"+env.getProperty("country"));
String class_id = env.getProperty("class_id[0]");
System.out.println("class_id===>"+class_id);
return country;
}
3. 使用类封装数据
@Autowired
private student student;
@GetMapping
public String getInfo(){
System.out.println(student.toString());
return student.toString();
}
package com.example.studaydemo_1.controller;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
// 定义数据模型封装数据
// 声明为Spring管控的Bean
@Component
// 指定加载的数据
@ConfigurationProperties(prefix = "student")
public class student {
private String name;
private int age;
private String class_id;
private String address;
public student() {
}
public student(String name, int age, String class_id, String address) {
this.name = name;
this.age = age;
this.class_id = class_id;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClass_id() {
return class_id;
}
public void setClass_id(String class_id) {
this.class_id = class_id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
", class_id='" + class_id + '\'' +
", address='" + address + '\'' +
'}';
}
}
4 整合第三方技术
4.1 整合JUnit
对于项目测试的技术整合
测试类
package com.studydemo_2;
import com.studydemo_2.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class StudyDemo2ApplicationTests {
// 1. 注入要测试的对象
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
// 2.执行要测试的方法
bookDao.save();
}
}
dao层
package com.studydemo_2.dao.impl;
import com.studydemo_2.dao.BookDao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("BookDao is running");
}
}
package com.studydemo_2.dao;
public interface BookDao {
public void save();
}
@SpringBootTest
- 类型:测试类注解
- 位置:测试类定义的上方
- 作用:设置JUnit加载的SpringBoot启动类
- 范例:
@SpringBootTest class StudyDemo2ApplicationTests { // 1. 注入要测试的对象 @Autowired private BookDao bookDao; @Test void contextLoads() { // 2.执行要测试的方法 bookDao.save(); }
- 属性:classes SpringBoot的启动类 启动文件
4.2 整合MyBatis
数据库连接和配置
数据库配置
# 配置数据库相关信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:// localhost:3306/test
username: root
password: root
数据接口
@Mapper
public interface BookDao {
@Select("select * from book where name = #{name}")
public Book findBookByName(String name);
}
测试类
@SpringBootTest
class StudyDemo3ApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
System.out.println(bookDao.findBookByName("百年孤独"));
}
}
4.3 整合MyBatis-Plus
与MyBatis的区别:导入坐标不同 实现数据层的简化
国人开发 在idea界面找不到 可以使用aliyun镜像导入或者手动导入Plus坐标
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
数据库配置和分层一致 使用增删改查的时候实现BaseMapper<泛型>即可
@Mapper
public interface BookDao extends BaseMpper<Book>{
}
需要进行Mp配置
4.4 整合Druid
数据库配置 需要手动导入坐标
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.24</version>
</dependency>
配置方式
# Druid常规配置数据库
#spring:
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql:// localhost:3306/test
# username: root
# password: 367343
# type: com.alibaba.druid.pool.DruidDataSource
# Druid连接池配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
min-idle: 5
max-active: 20
test-on-borrow: true
url: jdbc:mysql://localhost:3306/test
username: root
password: 367343
driver-class-name: com.mysql.cj.jdbc.Driver
导入任何第三方库
- 导入对应的starter
- 进行相关配置和默认设置
5 整合案例
完成一个基于SpringBoot的SSMP整合案例-图书管理系统 实现增删改查和分页展示的功能
5.1 实现目标
5.2 具体实现
5.2.1 配置文件
正常创建项目,然后导入数据库驱动,MyBatis-Plus,Druid的坐标
server:
port: 80
# 配置数据库相关信息
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
min-idle: 5
max-active: 20
test-on-borrow: true
url: jdbc:mysql://localhost:3306/test
username: root
password: 367343
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
global-config:
db-config:
id-type: auto # 主键生成策略
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启sql日志打印
5.2.2 数据层与其测试类
//lombok
//一个Java类库,提供了一组注解,简化POJO实体类开发
@Data // 生成getter/setter/toString/equals/hashCode等方法 是Getter和Setter的合并
public class Book {
private Integer id;
private String name;
private String author;
private String description;
}
书籍实体类 使用@Data注解自动生成getter和setter方法以及相关构造器
@Mapper
public interface BookDao extends BaseMapper<Book>{
}
使用快速开发的接口
5.2.3 服务层与其测试类
public interface BookService{
boolean save(Book book);
boolean update(Book book);
boolean delete(Book book);
Book getById(int id);
List<Book> getAll();
常规服务层接口
public interface IBookService extends IService<Book> {
IPage<Book> getPage(int currentPage, int pageSize);
IPage<Book> getPage(int currentPage, int pageSize, Book book);
}
快速开发服务层接口和扩展方法
// 快速开发方案
@Service
public class BookServiceImpl extends ServiceImpl<BookDao,Book> implements IBookService {
@Autowired
private BookDao bookDao;
@Override
public IPage<Book> getPage(int currentPage, int pageSize) {
IPage<Book> page = new Page<>(currentPage,pageSize);
bookDao.selectPage(page, null);
return page;
}
@Override
public IPage<Book> getPage(int currentPage, int pageSize, Book book) {
IPage<Book> page = new Page<>(currentPage,pageSize);
QueryWrapper<Book> lqw = new QueryWrapper<Book>();
if (StringUtils.isNotBlank(book.getName())) {
lqw.like("name", book.getName());
}
if (StringUtils.isNotBlank(book.getAuthor())) {
lqw.like("author", book.getAuthor());
}
if (StringUtils.isNotBlank(book.getDescription())) {
lqw.like("description", book.getDescription());
}
bookDao.selectPage(page, lqw);
return page;
}
// 可以继续追加其他业务方法 不要重载
}
快速开发接口实现类
5.2.4 控制层与其测试类
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService bookService;
@GetMapping
public R getAll() {
return new R(true,bookService.list());
}
@PostMapping
public R save(@RequestBody Book book) {
// R r = new R();
// Boolean flag = bookService.save(book);
// r.setFlag(flag);
// r.setData(null);
// return r;
boolean flag = bookService.save(book);
return new R(flag, flag ?"添加成功^_^":"添加失败-_-");
}
@PutMapping
public R update(@RequestBody Book book) {
return new R(bookService.updateById(book));
}
@DeleteMapping("/{id}")
public R delete(@PathVariable String id) {
return new R(bookService.removeById(id));
}
@GetMapping("/{id}")
public R getById(@PathVariable String id) {
return new R(true,bookService.getById(id));
}
// @GetMapping("/{currentPage}/{pageSize}")
// public R getPage(@PathVariable int currentPage,@PathVariable int pageSize){
//
// IPage<Book> page = bookService.getPage(currentPage,pageSize);
//
// if (currentPage > page.getPages()){
// page = bookService.getPage((int)page.getPages(),pageSize);
// }
//
// return new R(true,page);
// }
@GetMapping("/{currentPage}/{pageSize}")
public R getPage(@PathVariable int currentPage,@PathVariable int pageSize,Book book){
IPage<Book> page = bookService.getPage(currentPage,pageSize,book);
if (currentPage > page.getPages()){
page = bookService.getPage((int)page.getPages(),pageSize,book);
}
return new R(true,page);
}
}
对于增删改查操作的实现,以及向模型中注入分页后的数据
前后端信息传递
// 模型类 用于前后端数据的统一 前后端数据协议
@Data
public class R {
private Boolean flag;
private Object data;
private String msg;
public R() {
}
public R(Boolean flag) {
this.flag = flag;
}
public R(Boolean flag, Object data) {
this.flag = flag;
this.data = data;
}
public R(String msg) {
this.flag = false;
this.msg = msg;
}
}
异常处理类
@Configuration
public class MPConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
// MP定义拦截器
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 添加具体拦截器 分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
5.2.5 视图层与效果
这里使用的是黑马直接提供好的前端代码,这里展示一下HYML页面和一些相关设计,由于数据库设计的不同,这里对于表格模型进行了修改。
<!DOCTYPE html>
<html>
<head>
<!-- 页面meta -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>基于SpringBoot整合SSM案例</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.author style="width: 200px;" class="filter-item"></el-input>
<el-input placeholder="图书名称" v-model= pagination.name style="width: 200px;" class="filter-item"></el-input>
<el-input placeholder="图书描述" v-model= pagination.description 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="name" label="书名" align="center"></el-table-column>
<el-table-column prop="author" label="作者" align="center"></el-table-column>
<el-table-column prop="description" label="描述" align="center"></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="pagination-container">
<el-pagination
class="pagiantion"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-size="pagination.pageSize"
layout="total, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>
</div>
<!-- 新增标签弹层 -->
<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="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="作者" prop="author">
<el-input v-model="formData.author"/>
</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="cancel()">取消</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="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="作者" prop="author">
<el-input v-model="formData.author"/>
</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="cancel()">取消</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:{
dataList: [],//当前页要展示的列表数据
dialogFormVisible: false,//添加表单是否可见
dialogFormVisible4Edit:false,//编辑表单是否可见
formData: {},//表单数据
rules: {//校验规则
type: [{ required: true, message: '图书类别为必填项', trigger: 'blur' }],
name: [{ required: true, message: '图书名称为必填项', trigger: 'blur' }]
},
pagination: {//分页相关模型数据
currentPage: 1,//当前页码
pageSize:10,//每页显示的记录数
total:0,//总记录数
name:"",
author:"",
description:""
}
},
//钩子函数,VUE对象初始化完成后自动执行
created() {
this.getAll();
},
methods: {
//列表
// getAll() {
// // 异步请求
// axios.get("/books").then(response => {
// this.dataList = response.data.data;
// });
//
// },
//分页查询 在全部查询的基础上进行分页查询的编辑
getAll() {
param = "?temp" + "&name="+this.pagination.name+"&author="+this.pagination.author+"&description="+this.pagination.description;
// 异步请求
axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize + param).then(response => {
this.pagination.pageSize = response.data.data.size;
this.pagination.currentPage = response.data.data.current;
this.pagination.total = response.data.data.total;
this.dataList = response.data.data.records;
});
},
//切换页码
handleCurrentChange(currentPage) {
this.pagination.currentPage = currentPage;
this.getAll();
},
//条件查询
handleSearch() {
axios.get("/books", {
params: {
page: this.pagination.currentPage,
size: this.pagination.pageSize,
type: this.formData.type,
name: this.formData.name
}
}).then(response => {
this.dataList = response.data.data;
});
},
//弹出添加窗口
handleCreate() {
this.dialogFormVisible = true;
this.resetForm();
},
//重置表单
resetForm() {
this.formData = {};
},
//添加
handleAdd () {
axios.post("/books", this.formData).then(response => {
// 判断是否成功
if(response.data.flag){
// 1. 关闭弹层
this.dialogFormVisible = false;
this.$message.success("添加成功!");
}
else{
this.$message.error("添加失败!");
}
}).finally(()=>{
// 2. 刷新数据
this.getAll();
});
},
//取消
cancel(){
this.dialogFormVisible = false;
this.dialogFormVisible4Edit = false;
this.resetForm();
// 提示
this.$message({
type: 'info',
message: '取消成功'
});
},
// 删除
handleDelete(row) {
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.delete("/books/" + row.id).then(res => {
// 判断是否成功
if(res.data.flag){
this.$message({
type: 'success',
message: '删除成功!'
})
this.getAll();
}
else{
this.$message.error("同步失败! 自动刷新");
}
})
}).finally(() => {
// 加载数据
this.getAll();
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
})
},
//弹出编辑窗口
handleUpdate(row) {
axios.get("/books/"+row.id).then(response => {
if(response.data.flag && response.data.data != null) {
this.dialogFormVisible4Edit = true;
this.formData = response.data.data;
}else{
this.$message.error("同步失败! 自动刷新");
}
}).finally(()=>{
this.getAll();
});
if(response.data.flag){
// 1. 关闭弹层
this.dialogFormVisible4Edit = false;
this.dialogFormVisible4Edit = false;
this.$message.success("修改成功!");
}
else{
this.$message.error("修改失败!");
}
},
//修改
handleEdit() {
axios.put("/books", this.formData).then(response => {
// 判断是否成功
if(response.data.flag){
// 1. 关闭弹层
this.dialogFormVisible4Edit = false;
this.$message.success(res.data.msg);
}
else{
this.$message.error(res.data.msg);
/**
his.$message.success("修改成功!");
this.$message.error(res.data.msg);
这里出现了前后端都要传递数据的情况
可以全部交给前端处理 这里使用全部使用后端处理的方式
*/
}
}).finally(()=>{
// 2. 刷新数据
this.getAll();
});
},
}
})
</script>
</html>
6 常用注解
Spring Boot注解主要用于简化配置、自动装配组件和实现声明式服务。
文章位置:springboot常用注解大全(超详细, 30个)-CSDN博客
注解分类 | 注解名 | 位置 | 作用 |
---|---|---|---|
核心注解 | @SpringBootApplication | Spring Boot 的主类上 | Spring Boot 最核心的注解,是 @Configuration、@EnableAutoConfiguration、@ComponentScan 三个注解的组合,用来开启 Spring Boot 的各项能力 |
自动配置相关 | @EnableAutoConfiguration | 类上 | 允许 Spring Boot 自动配置注解,能根据当前类路径下的包或类来配置 Spring Bean。关键在于引入 AutoConfigurationImportSelector,其 selectImports 方法会从配置文件 META-INF/spring.factories 加载所有可能用到的自动配置类,去重并排除 exclude 和 excludeName 属性携带的类,过滤并返回满足 @Conditional 条件的自动配置类 |
配置相关 | @Configuration | 类上 | 用于定义配置类,是 Bean 配置的信息源,相当于传统的 xml 配置文件,可加在主类上;若第三方库需用 xml 文件,可使用 @ImportResource 注解通过该类加载 xml 配置文件 |
组件扫描相关 | @ComponentScan | 类上 | 让 Spring Boot 扫描到 Configuration 类并将其加入到程序上下文,默认会装配标识了 @Controller、@Service、@Repository、@Component 注解的类到 spring 容器中 |
数据访问组件 | @Repository | 类上 | 用于标注数据访问组件(DAO 组件),可确保 DAO 或 repositories 提供异常转译,会被 ComponetScan 发现并配置,无需 XML 配置项 |
服务层组件 | @Service | 类上 | 一般用于修饰 service 层的组件 |
控制层组件 | @RestController | 类上 | 用于标注控制层组件,是 REST 风格的控制器,是 @Controller 和 @ResponseBody 的合集,将函数的返回值直接填入 HTTP 响应体中 |
响应体相关 | @ResponseBody | 方法上 | 表示该方法的返回结果直接写入 HTTP response body 中,一般在异步获取数据时使用,使用 @RequestMapping 后,加此注解可避免返回值被解析为跳转路径,直接返回数据(如 json) |
通用组件 | @Component | 类上 | 泛指组件,当组件不好归类时使用此注解标注 |
Bean 管理 | @Bean | 方法上 | 相当于 XML 中的<bean>,产生一个 bean 并交给 spring 管理 |
自动装配 | @AutoWired | 类成员变量、方法及构造函数上 | byType 方式,把配置好的 Bean 拿来用,完成属性、方法的组装,自动装配工作,加(required=false)时,找不到 bean 不报错 |
自动装配辅助 | @Qualifier | 类成员变量、方法及构造函数上 | 当有多个同一类型的 Bean 时,与 @Autowired 配合使用,用 @Qualifier ("name") 来指定具体 Bean |
自动装配 | @Resource | 类成员变量、方法及构造函数上 | 无括号内内容时默认 byName,与 @Autowired 类似 |
请求映射 | @RequestMapping | 类或方法上 | 用来处理请求地址映射,提供路由信息,负责 URL 到 Controller 中具体函数的映射,用于类上时表示类中所有响应请求的方法以该地址作为父路径 |
请求参数 | @RequestParam | 方法的参数前面 | 用于方法的参数,如 @RequestParam String a = request.getParameter ("a") |
路径变量 | @PathVariable | 方法的参数上 | 路径变量,参数与大括号里的名字要相同,如 @RequestMapping ("user/get/mac/{macAddress}"),可在方法参数中使用 @PathVariable String macAddress 获取路径变量 |
环境配置 | @Profiles | 类上 | Spring Profiles 提供一种隔离应用程序配置的方式,让这些配置只能在特定环境下生效,可标记 @Component 或 @Configuration 以限制加载时机 |
配置映射 | @ConfigurationProperties | 类上 | Spring Boot 使用此注解将自定义的 properties 文件映射到实体 bean 中,如将 config.properties 文件映射到类中 |
7 周末总结
这一周学习了一下SpringBoot的一些基础知识内容,包括入门和综合SSMP案例的练习。主要是根据黑马程序员的课程逐步完善代码,由于之前并没有使用过Spring,并不能理解SprigBoot的便捷性。对于MVC分层的程序,根据需求逐步完成项目的过程中,学习了表格模型的增删改查操作。以及分页和相关显示和一些事务的处理,譬如删除元素后停留在没有元素的空页面。这些需要一些经验。另外对于前端的开发,整合案例中使用了axios的模型,这部分比较陌生,需要学习一下。然后,在基本了解了一个简单项目开发后,后续需要进行项目练习和mevan知识的复习。
学习时间 2025.1.9 - 2025.1.13