springBoot
基础篇
快速上手
入门案例
最简单springBoot程序所包含的基础文件
- pom.xml
- Application类
@SpringBootApplication
public class SpringBoot0101quickstartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot0101quickstartApplication.class, args);
}
}
与普通spring对比
入门案例解析
parent
- 定义了一系列常用的坐标版本
- 定义一系列常用坐标组合
- 直接就可以使用组合
starter
引导类
- 整个程序的入口,由
@SpringBootApplication
来标志 - 初始化spring容器,扫描引导类所在的包加载bean
@SpringBootApplication
public class SpringBoot0101quickstartApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringBoot0101quickstartApplication.class, args);
}
}
内嵌tomcat
将tomcat执行对象进行抽取,并将其交给spring进行管理
boot内置三款服务器
- tomcat(默认):应用面广
- jetty:轻量级
- undertow:负载勉强超过tomcat
基础配置
属性配置
- 默认配置文件
application.properties
,通过键值对配置对应属性
支持三种格式
-
properties(主导)
server.port=8080
-
yml(主流)
server: port: 8808
-
yaml(优先度最低)
server: port: 8809
三种配置文件按照优先度进行(相同)覆盖,(不同)叠加
yaml语法规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Qdyz3g7-1651639078951)(https://gitee.com/fatem/markdown_imgs/raw/master/img/202205021655670.png)]
#单一数据
city: cengdu
#对象
user:
name: fate
age: 18
#数组
habbys:
- code
- game
- music
likes: [game,sleep]
#对象数组
users:
-
name: zore
age: 26
-
name: ddd
age: 29
persons: [{name:fate,age:18},{name:zore,age:24}]
数据的调用
package com.fate.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author m
*/
@RestController
@RequestMapping("/books")
public class Testcontroller {
@Value("${city}")
String city;
@Value("${user.age}")
Integer age;
@Value("${habbys[1]}")
String hobby;
@RequestMapping
public String city(){
System.out.println(city);
System.out.println(age);
System.out.println(hobby);
return city;
}
}
读取yml所有数据
@Autowired
private Environment environment;
获取
System.out.println(environment.getProperty("city"));
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AipGJteH-1651639078952)(https://gitee.com/fatem/markdown_imgs/raw/master/img/202205021847180.png)]
读取yml对象数据
datasource:
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/mybatis
username: root
password: mzf200314
package com.fate;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author m
*/
@Component
@ConfigurationProperties("datasource")
public class MyDataSource {
private String driver;
private String url;
private String username;
private String password;
@Override
public String toString() {
return "MyDataSource{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@Autowired
MyDataSource dataSource;
整合第三方技术
junit(自带)
mybatis
-
创建boot工程
-
勾选mybatis和数据库驱动
-
在
application.yml
中配置数据源参数#mybatis配置 spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/spring5?useUnicode=true&characterEncoding=utf8 username: root password: mzf200314
小结
常见问题
MyBatis-plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
Druid
导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.9</version>
</dependency>
两种配置方式
##第一种
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring5?useUnicode=true&characterEncoding=utf8
username: root
password: mzf200314
type: com.alibaba.druid.pool.DruidDataSource
#德鲁伊专用
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/spring5?useUnicode=true&characterEncoding=utf8
username: root
password: mzf200314
driver-class-name: com.mysql.jdbc.Driver
ssmp整合
lombok
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
@Data
自动生成get/set
@Data
public class Book {
private Integer id;
private String type;
private String name;
private String description;
public Book(Integer id, String type, String name, String description) {
this.id = id;
this.type = type;
this.name = name;
this.description = description;
}
public Book() {
}
}
分页
添加mp的分页拦截器
@Configuration
public class MPConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
@Test
void test(){
Page<Book> bookPage = new Page<>(1,5);
mapper.selectPage(bookPage,null);
System.out.println(bookPage);
}
小结
条件查询
@Test
void Wrapper1(){
QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name","spring");
mapper.selectList(queryWrapper).forEach(System.out::println);
}
@Test
void Wrapper2(){
LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(Book::getName,"spring");
mapper.selectList(queryWrapper).forEach(System.out::println);
}
小结
业务层开发
crud…
package com.fate.srevice;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fate.domain.Book;
import java.util.List;
/**
* @author m
*/
public interface BookService {
boolean save(Book book);
boolean update(Book book);
boolean delete(Integer id);
Book getBookById(Integer id);
List<Book> getAll();
Page<Book> getPage(int currentPage,int pageSize);
}
package com.fate.srevice.imp;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fate.domain.Book;
import com.fate.mapper.BookMapper;
import com.fate.srevice.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author m
*/
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookMapper bookMapper;
@Override
public boolean save(Book book) {
return bookMapper.insert(book)>0;
}
@Override
public boolean update(Book book) {
return bookMapper.update(book,null)>0;
}
@Override
public boolean delete(Integer id) {
return bookMapper.deleteById(id)>0;
}
@Override
public Book getBookById(Integer id) {
return bookMapper.selectById(id);
}
@Override
public List<Book> getAll() {
return bookMapper.selectList(null);
}
@Override
public Page<Book> getPage(int currentPage, int pageSize) {
Page<Book> bookPage = new Page<>(currentPage, pageSize);
return bookMapper.selectPage(bookPage,null);
}
}
小结
业务层开发(mp懒狗模式)
继承之后直接用
package com.fate.srevice;
import com.baomidou.mybatisplus.extension.service.IService;
import com.fate.domain.Book;
/**
* @author m
*/
public interface IBookService extends IService<Book> {
}
package com.fate.srevice.imp;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fate.domain.Book;
import com.fate.mapper.BookMapper;
import com.fate.srevice.IBookService;
import org.springframework.stereotype.Service;
/**
* @author m
*/
@Service
public class IBookServiceImpl extends ServiceImpl<BookMapper, Book> implements IBookService {
}
小结
基于Restful制作表现层
package com.fate.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fate.domain.Book;
import com.fate.srevice.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author m
*/
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService iBookService;
@GetMapping
private List<Book> getAll(){
return iBookService.list();
}
@PostMapping
private Boolean save(@RequestBody Book book){
return iBookService.save(book);
}
@PutMapping
public Boolean update(@RequestBody Book book){
return iBookService.update(book);
}
@DeleteMapping("{id}")
public Boolean delete(@PathVariable Integer id){
return iBookService.removeById(id);
}
@GetMapping("{id}")
public Book getById(@PathVariable Integer id){
return iBookService.getById(id);
}
@GetMapping("{index}/{size}")
public IPage<Book> getPage(@PathVariable Integer index, @PathVariable Integer size){
return iBookService.getPage(index,size);
}
}
表现层消息一致性处理
package com.fate.controller.utils;
import lombok.Data;
/**
* @author m
*/
@Data
public class Result {
private boolean flag;
private Object data;
public Result() {
}
public Result(boolean flag) {
this.flag = flag;
}
public Result(boolean flag, Object data) {
this.flag = flag;
this.data = data;
}
}
前后端协议联调
- 前后端分离结构设计中页面归属于前端服务器
- 单体工程中页面放置在resource/static目录下
<!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.type" 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="type" label="图书类别" align="center"></el-table-column>
<el-table-column prop="name" 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="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="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="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="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,//总记录数
type: "",
name: "",
description: ""
}
},
//钩子函数,VUE对象初始化完成后自动执行
created() {
//调用查询全部数据的操作
this.getAll();
},
methods: {
//列表
getAll1() {
//发送异步请求
axios.get("/books").then((res)=>{
// console.log(res.data);
this.dataList = res.data.data;
});
},
//分页查询
getAll() {
let param={
type:this.pagination.type,
name:this.pagination.name,
description:this.pagination.description
}
axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+"?type="+param.type+"&name="+param.name+"&description="+param.description).then((res)=>{
if (res.data.flag){
this.dataList=res.data.data.records;
this.pagination.total=res.data.data.total;
this.pagination.currentPage=res.data.data.current;
this.pagination.pageSize=res.data.data.size;
}
});
},
//切换页码
handleCurrentChange(currentPage) {
//修改页码值为当前选中的页码值
this.pagination.currentPage = currentPage;
//执行查询
this.getAll();
},
//弹出添加窗口
handleCreate() {
this.dialogFormVisible = true;
this.resetForm();
},
//重置表单
resetForm() {
this.formData = {};
},
//添加
handleAdd () {
let that=this;
axios.post("/books",this.formData).then((res)=>{
if(res.data.flag){
that.dialogFormVisible=false;
that.$message.success("添加成功!");
}else {
that.$message.error("添加失败");
}
}).finally(()=>{
that.getAll();
});
},
//取消
cancel(){
this.dialogFormVisible = false;
this.dialogFormVisible4Edit = false;
this.$message.info("当前操作取消");
},
// 删除
handleDelete(row) {
this.$confirm("真的要删除"+row.name+"吗?","亚达哟😭",{type:"info"}).then(()=>{
axios.delete("/books/"+row.id).then((res)=>{
if(res.data.flag){
this.$message.success("好似🍾!");
}else {
this.$message.error("败北");
}
}).finally(()=>{
this.getAll();
});
}).catch(()=>{
this.$message.info("想逃?😤");
});
},
//弹出编辑窗口
handleUpdate(row) {
axios.get("/books/"+row.id).then((res)=>{
if(res.data.flag&&res.data.data!=null){
this.dialogFormVisible4Edit=true;
this.formData=res.data.data;
}else{
this.$message.error("怎么会是呢?");
}
}).finally(()=>{
this.getAll();
});
},
//修改
handleEdit() {
axios.put("/books",this.formData).then((res)=>{
if(res.data.flag){
this.$message.success("修改成功");
this.dialogFormVisible4Edit=false;
}else {
this.$message.error("修改失败");
}
}).finally(()=>{
this.getAll();
});
},
//条件查询
}
})
</script>
</html>