//Rest模式
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping
public String getById(){
System.out.println("springboot is running...");
return "springboot is running...";
}
}
最简SpringBoot程序所包含的基础文件
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.1.4version>
<relativePath/>
parent>
<groupId>com.SmulllgroupId>
<artifactId>springboot_01_02artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>springboot_01_02name>
<description>springboot_01_02description>
<properties>
<java.version>17java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
project>
@SpringBootApplication
public class Springboot0102Application {
public static void main(String[] args) {
SpringApplication.run(Springboot0102Application.class, args);
}
}
Spring程序与SpringBoot程序对比
类/配置文件 | Spring | SpringBoot |
---|---|---|
pom文件中的坐标 | 手工添加 | 勾选添加 |
web3.0配置类 | 手工制作 | 无 |
Spring/SpringMVC配置类 | 手工制作 | 无 |
控制器 | 手工制作 | 手工制作 |
创建项目也可以通过官网进行创建
springboot项目创建官网
阿里云提供的坐标版本较低,如果需要使用高版本,进入工程后手工切换SpringBoot版本阿里云提供的工程模板与Spring官网提供的工程模板略有不同
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.1.4version>
<relativePath/>
parent>
<groupId>com.SmulllgroupId>
<artifactId>springboot_01_02artifactId>
<version>0.0.1-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
project>
@SpringBootApplication
public class Springboot0102Application {
public static void main(String[] args) {
SpringApplication.run(Springboot0102Application.class, args);
}
}
SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程
Spring程序缺点
SpringBoot程序优点
spring-boot-starter-parent
spring-boot-starter-parent
中定义了若干个依赖管理<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<version>2.5.4version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>springwebartifactId>
<version>5.3.9version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.9version>
dependency>
dependencies>
starter
parent
实际开发
@SpringBootApplication
public class Springboot0102Application {
public static void main(String[] args) {
SpringApplication.run(Springboot0102Application.class, args);
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
在其内部导入一个
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<version>2.5.4version>
dependency>
其内部有个核心包进行运行
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-coreartifactId>
<version>9.0.52version>
dependency>
内置服务器
REST (Representational State Transfer),表现形式状态转换
优点:
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
根据REST风格对资源进行访问称为RESTful
注意事项
上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如: users、books、accounts…
@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody User user){
System.out.println("user update..."+user);
return "{'module':'user update'}";
};
@RequestMapping(value = "/users/{id}",method = RequestMethod.GET)
@ResponseBody
public String getById(@PathVariable Integer id){
System.out.println("user getById..."+id);
return "{'module':'user getById'}";
};
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save(){
System.out.println("user save...");
return "{'module':'user save'}";
};
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println("user delete..."+id);
return "{'module':'user delete'}";
};
接收参数的三种方式
@RequestBody @RequestRaram @PathVariable
@RequestMapping(value = "/books",method=RequestMethod.POST)
@ResponseBody
public String save(@RequestBody Book book){
system.out.println("book save. . ." + book);
return "{'module':'book save'}";
}
@RequestMapping(value = "/books",method=RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody Book book){
system.out.println( "book update. . . "+book);
return "{'module':'book update'}";
}
@RestController
public class BookController{
}
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("user getById..."+id);
return "{'module':'user getById'}";
};
复制工程
SpringBoot默认配置文件application.properties,通过键值对配置对应属性
修改配置
server.port=80
spring.main.banner-mode=off
logging.level.root = error
SpringBoot内置属性查询
server.port=80
server:
port: 81
server:
port: 82
SpringBoot配置文件加载顺序
properties
> application.yml
>application.yaml
不同配置文件中相同配置按照加载优先级相互覆盖,不同配置文件中不同配置全部保留
yaml语法规则
#
表示注释boolean: TRUE #TRUE ,true ,True ,FALSE,false ,False均可
float: 3.14 #6.8523015e+5#支持科学计数法
int: 123 #0b1010_0111_0100_1010_1110#支持二进制、八进制、十六进制
null: ~ #使用~表示null
string: Helloworld #字符串可以直接书写
string2: "Hello world" #可以使用双引号包裹特殊字符
date: 2018-02-17 #日期必须使用yyyy-MM-dd格式
datetime: 2018-02-17T15:02:31+08:00 #时间和日期之间使用T连接,最后使用+代表时区
likes:
- game
- sleep
- music
user1:
name: zhangsan
age: 23
likes:
- Java
- 前端
- 大数据
likes1: [game,sleep,music]
${一级属性名.二级属性名...}
likes:
- game
- sleep
- music
user1:
name: zhangsan
age: 23
@RestController
@RequestMapping("/Books")
public class BookController {
@Value("${country}")
private String country1;
@Value("${user1.name}")
private String name1;
@Value("${likes[1]}")
private String likes;
}
baseDir: /usr/ local/fire
center:
dataDir: ${baseDir}/data
tmpDir: ${baseDir}/tmp
logDir: ${baseDir}/log
msgDir: ${baseDir}/msgDir
lession: "Spring\tboot\nlesson"
@RestController
@RequestMapping("/Books")
public class BookController {
@Autowired
private Environment environment;
@GetMapping
public void Books(){
System.out.println(environment.getProperty("user1.name"));
System.out.println(environment.getProperty("likes[1]"));
}
}
likes:
- game
- sleep
- music
user1:
name: zhangsan
age: 23
datasource:
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/springboot_db
username: root
password: 123456
@Component
@ConfigurationProperties("datasource")
public class Datasource {
private String driver;
private String url;
private String username;
private String password;
public Datasource() {
}
public Datasource(String driver, String url, String username, String password) {
this.driver = driver;
this.url = url;
this.username = username;
this.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;
}
public String toString() {
return "Datasource{driver = " + driver + ", url = " + url + ", username = " + username + ", password = " + password + "}";
}
}
@RestController
@RequestMapping("/Books")
public class BookController {
@Autowired
private Datasource datasource;
}
@SpringBootTest
class Springboot0101ApplicationTests {
@Autowired
private BooksDao booksDao;
@Test
void contextLoads() {
booksDao.save();
}
}
@SpringBootTest
class Springboot0101ApplicationTests {}
@SpringBootTest(classes = Springboot0101Application.class )
class Springboot0101ApplicationTests {}
注意事项
如果测试类在SpringBoot启动类的包或子包中,可以省略启动类的设置,也就是省略classes的设定
步骤:
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbase
username: root
password: xxxxxx
@Mapper
public interface AccountDao {
@Select("select * from tb_account where id = #{id}")
public Account SelectById(Integer id);
}
@SpringBootTest
class Springboot03MybatisApplicationTests {
@Autowired
private AccountDao accountDao;
@Test
void contextLoads() {
Account account = accountDao.SelectById(1);
System.out.println(account);
}
}
注意:
MySQL 8.X驱动强制要求设置时区
驱动类过时,提醒更换为com.mysql.cj.jdbc.Driver
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.3.1version>
dependency>
注意事项:
由于SpringBoot中未收录MyBatis-plus的坐标版本,需要指定对应的Version
@Mapper
public interface AccountDao extends BaseMapper<Account> {
}
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbase?serverTimezone=UTC
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.2.19version>
dependency>
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbase?serverTimezone=UTC
username: root
password: 123456
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
@Data
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.3.1version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.2.19version>
dependency>
server:
port: 80
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbootbase?serverTimezone=UTC
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
global-config:
db-config:
table-prefix: tb_
id-type: auto
@Mapper
public interface bookDao extends BaseMapper<Book> {
}
@SpringBootTest
public class bookTestCase {
@Autowired
private bookDao bookDao;
@Test
void TestSelectById(){
Book book = bookDao.selectById(1);
System.out.println(book);
}
}
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
@Test
void TestGetPage(){
Page page = new Page(1,5);
bookDao.selectPage(page,null);
}
IPage对象中封装了分页操作中的所有数据
分页操作是在MNyBatisPlus的常规操作基础上增强得到,内部是动态的拼写SQL语句,因此需要增强对应的功能,使用MyBatisPlus拦截器实现
@Configuration
public class MPConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//定义MP拦截器
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//添加具体的拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
@Test
void TestGetBy(){
QueryWrapper<Book> qw = new QueryWrapper<>();
qw.like("name", "Spring");
bookDao.selectList(qw);
}
@Test
void TestGetBy2(){
String name = "Spring";
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
//当name不等于null时走该语句
lqw.like(name!=null,Book::getName, name);
//执行分页查询加上条件查询
Page page = new Page(1,5);
bookDao.selectPage(page,lqw);
}
Service层接口定义与数据层接口定义具有较大区别,不要混用
selectByUserNameAndPassword (String username,String password);
login (String username,String password);
定义接口
public interface BookService {
Boolean save(Book book);
Boolean update(Book book);
Boolean delete(Integer id);
Book getById(Integer id);
List<Book> getAll();
IPage<Book> getByPage(Integer current,Integer size);
}
@Service
public class BookServiceImpl implements BookService {
@Autowired
private bookDao bookDao;
@Override
public Boolean save(Book book) {
return bookDao.insert(book)>0;
}
@Override
public Boolean update(Book book) {
return bookDao.updateById(book)>0;
}
@Override
public Boolean delete(Integer id) {
return bookDao.deleteById(id)>0;
}
@Override
public Book getById(Integer id) {
return bookDao.selectById(id);
}
@Override
public List<Book> getAll() {
return bookDao.selectList(null);
}
@Override
public IPage<Book> getByPage(Integer current, Integer size) {
Page<Book> bookPage = new Page<>(current, size);
bookDao.selectPage(bookPage,null);
return bookPage;
}
}
@SpringBootTest
public class bookServiceTestCase {
@Autowired
private BookService bookService;
@Test
void getById(){
Book byId = bookService.getById(1);
System.out.println(byId);
}
@Test
void getAll(){
List<Book> all = bookService.getAll();
System.out.println(all);
}
@Test
void testPage(){
IPage<Book> byPage = bookService.getByPage(0, 5);
System.out.println(byPage.getPages());
System.out.println(byPage.getCurrent());
System.out.println(byPage.getSize());
System.out.println(byPage.getTotal());
System.out.println(byPage.getRecords());
}
}
快速开发方案
定义接口
public interface IBookService extends IService<Book> {
}
public interface IBookService extends IService<Book> {
Boolean delete(Book book);
Boolean insert(Book book);
}
@Service
public class BookServiceImpl extends ServiceImpl<bookDao,Book> implements IBookService {
@Override
public Boolean delete(Book book) {
return null;
}
@Override
public Boolean insert(Book book) {
return null;
}
}
@RestController
@RequestMapping("/books")
public class bookController {
@Autowired
private IBookService iBookService;
@GetMapping
public List<Book> GetAll(){
return iBookService.list();
}
@PostMapping
public Boolean save(@RequestBody Book book){
boolean save = iBookService.save(book);
return save;
}
@PutMapping
public Boolean update(@RequestBody Book book){
boolean b = iBookService.updateById(book);
return b;
}
@DeleteMapping("/{id}")
public Boolean delete(@PathVariable Integer id){
boolean b = iBookService.removeById(id);
return b;
}
@GetMapping("/{id}")
public Book getById(@PathVariable Integer id){
return iBookService.getById(id);
}
@GetMapping("{current}/{size}")
public IPage<Book> getPage(@PathVariable Integer current,@PathVariable Integer size){
return iBookService.getPage(current,size);
}
}
@Override
public Page<Book> getPage(Integer current, Integer size) {
Page<Book> bookPage = new Page<>(current, size);
return bookDao.selectPage(bookPage, null);
}
true
{
"id": 5,
"type": "操作系统",
"name": "深入理解计算机系统",
"description": "这本书是一本导论型作品,并不单单的讲操作系统,它创造性的把操作系统,体系结构,数字逻辑,以及编译原理这些计算机基础学科知识有机的结合起来。"
}
[
{
"id": 1,
"type": "计算机理论",
"name": "Spring实战 第五版",
"description": "Spring经典入门教学,深入理解Spring理解技术内幕"
},
{
"id": 2,
"type": "计算机理论",
"name": "Spring实战 第五版",
"description": "Spring经典入门教学,深入理解Spring理解技术内幕"
},
{
"id": 3,
"type": "计算机理论",
"name": "Spring实战 第五版",
"description": "Spring经典入门教学,深入理解Spring理解技术内幕"
},
{
"id": 4,
"type": "操作系统",
"name": "现代操作系统",
"description": "本书虽然是理论的书,但是里面的一些操作系统算法介绍都挺非常的详细,有关操作系统的各种理论也是非常详实。"
},
{
"id": 5,
"type": "操作系统",
"name": "深入理解计算机系统",
"description": "这本书是一本导论型作品,并不单单的讲操作系统,它创造性的把操作系统,体系结构,数字逻辑,以及编译原理这些计算机基础学科知识有机的结合起来。"
}
]
@Data
public class R {
private Boolean flag;
private Object data;
public R(Boolean flag) {
this.flag = flag;
}
public R() {
}
public R(Boolean flag, Object data) {
this.flag = flag;
this.data = data;
}
}
@RestController
@RequestMapping("/books")
public class bookController {
@Autowired
private IBookService iBookService;
@GetMapping
public R GetAll(){
return new R(true,iBookService.list());
}
@PostMapping
public R save(@RequestBody Book book){
return new R(iBookService.save(book));
}
@PutMapping
public R update(@RequestBody Book book){
return new R(iBookService.updateById(book));
}
@DeleteMapping("/{id}")
public R delete(@PathVariable Integer id){
return new R(iBookService.removeById(id));
}
@GetMapping("/{id}")
public R getById(@PathVariable Integer id){
return new R(true,iBookService.getById(id));
}
@GetMapping("{current}/{size}")
public R getPage(@PathVariable Integer current,@PathVariable Integer size){
return new R(true,iBookService.getPage(current,size));
}
}
//列表
getAll(){
axios.get("/books").then((res)=>{
console.log(res.data)
})
}
//添加
handleAdd () {
//发送异步请求
axios.post("/books",this.formData).then((res)=>{
//如果操作成功,关闭弹层,显示数据
if(res.data.flag)
this.dialogFormVisible = false;
this.$message.success("添加成功");
}else {
this.$message.error("添加失败");
}
}).finally(()=>{
this.getAl1();
});
},
//删除
handleDelete(row){
axios.delete("/books/"+row.id).then((res)=>{
if(res.data.flag){
this.$message.success("删除成功");
}else{
this.$message.error("数据同步失败,自动刷新");
}
}).finally(()=>{
this.getAll();
});
}
改进删除操作
handleDelete(row) {
//1.弹出提示框
this.$confirm("此操作永久删除当前数据,是否继续? ","提示",{
type:'info'
}).then(()=>{
//2.做删除业务
axios.delete("/books/"+row.id).then((res)=>{
......
}).finally(()=>{
this.getAl1();
});
}).catch(()=>{
//3.取消删除
this.$message.info("取消删除操作");
});
}
//弹出编辑窗口
handleUpdate(row){
axios.get("/books/"+row.id).then((res)=>{
if(res.data.flag){
//展示弹层,加载数据
this.formData = res.data.data;
this.dialogFormVisible4Edit = true;
}else{
this.$message.error("数据同步失败,自动刷新");
}
});
},
//修改
handleAdd () {
//发送异步请求
axios.put("/books",this.formData).then((res)=>{
//如果操作成功,关闭弹层,显示数据
if(res.data.flag)
this.dialogFormVisible4Edit = false;
this.$message.success("修改成功");
}else {
this.$message.error("修改失败");
}
}).finally(()=>{
this.getAl1();
});
},
cancel(){
this.dialogFormVisible = false;
this.dialogFormVisible4Edit = false;
this.$message.info("操作取消");
},
{
"flag": true,
"data": null
}
{
"flag": false,
"data": null
}
{
"timestamp": "2021-09-15T03:27:31.038+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/books"
}
//作为SpringMVC的异常处理器
@ControllerAdvice
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler
public R doException(Exception ex){
//记录日志
//通知运维
//通知开发
ex.printStackTrace();
return new R("服务器故障,请稍后重试");
}
}
@Data
public class R {
private Boolean flag;
private Object data;
private String Message;
public R(Boolean flag, String message) {
this.flag = flag;
this.Message = message;
}
}
@PostMapping
public R save(@RequestBody Book book){
boolean flag = iBookService.save(book);
return new R(flag,flag?"添加成功^_^":"添加失败-_-!");
}
<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>
data:{
pagination: { //分页相关模型数据
currentPage: 1, //当前页码
pageSize:10, //每页显示的记录数
total:0, //总记录数
}
},
getAll(){
axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res)=>{
});
}
getAll(){
axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res)=>{
this.pagination.total = res.data.data.total;
this.pagination.currentPage = res.data.data.current;
this.pagination.pagesize = res.data.data.size;
this.datalist = res.data.data.records;
});
}
//切换页码
handleCurrentChange(currentPage) {
this.pagination.currentPage = currentPage;
this.getAll();
},
@GetMapping("{current}/{size}")
public R getPage(@PathVariable Integer current,@PathVariable Integer size){
Page<Book> page = iBookService.getPage(current, size);
if (current>page.getPages()){
page = iBookService.getPage((int)page.getPages(), size);
}
return new R(true,page );
}
pagination: { //分页相关模型数据
currentPage: 1, //当前页码
pagesize:10, //每页显示的记录数
total:0, //总记录数
name: "",
type: "",
description: ""
}
<div class="filter-container">
<el-input placeholder="图书类别"v-model="pagination.type" class="filter-item"/>
<el-input placeholder="图书名称"v-model="pagination.name" class="filter-item" />
<el-input placeholder="图书描述"v-model="pagination.description" class="filter-item" />
<el-button @click="getAll()" class="dalfBut">查询el-button>
<el-button type="primary" class="butT" @click="handleCreate()">新建el-button>
div>
getAll() {
//1.获取查询条件,拼接查询条件
param = "?name="+this.pagination.name;
param += "&type="+this.pagination.type;
param += "&description="+this.pagination.description;
console.log("-----------------"+param) ;
axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param)
.then((res) => {
this.dataList = res.data.data.records;
});
},
@GetMapping("{current}/{size}")
public R getPage(@PathVariable Integer current,@PathVariable Integer size,Book book){
Page<Book> page = iBookService.getPage(current, size,book);
if (current>page.getPages()){
page = iBookService.getPage((int)page.getPages(), size,book);
}
return new R(true,page );
}
@Override
public Page<Book> getPage(Integer current, Integer size, Book book) {
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
lqw.like(Strings.isNotEmpty(book.getType()),Book::getType,book.getType());
lqw.like(Strings.isNotEmpty(book.getName()),Book::getName,book.getName());
lqw.like(Strings.isNotEmpty(book.getDescription()),Book::getDescription,book.getDescription());
Page<Book> bookPage = new Page<>(current, size);
return bookDao.selectPage(bookPage, lqw);
}