天狗实战SpringBoot API开发详解 --SpringMVC注解+封装结果+支持跨域+打包(下)
Posted 天罡gg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了天狗实战SpringBoot API开发详解 --SpringMVC注解+封装结果+支持跨域+打包(下)相关的知识,希望对你有一定的参考价值。
本文目录
前言
在上文,我们基于Maven,已经把三层架构项目搭建起来了,重点掌握的是如何规范的创建Maven项目、如何统一管理依赖版本。还没掌握的同学,可以先看看上文:天狗实战SpringBoot+Vue(二)项目结构搭建(上)
本文,将基于上文搭建的项目结构,开始创建SpringBoot项目,并进行API开发,最终输出给前端两个API:分别基于GET和POST 请求。
从实现层面:会结合实战 解读SpringMVC常用注解的使用,并实现 API结果统一封装、 支持跨域请求,以及 多Jar如何打包。
从规范层面:会结合实战 把 三层架构 都串起来,包括各层的命名规范和对象职责。
这些都是实际项目必须掌握的,所以跟上节奏,Let’s Go!
对应思维导图的红框处:
专栏介绍
因为可能还有很多同学还不清楚上下文,所以简单介绍一下这个专栏要做的事:
天罡老哥和狗哥(博客主页)有意
从0到1
带大家搭建一个SpringBoot+SpringCloud+Vue
的前后端分离项目!
打造一个短小精悍、技术主流、架构规范的前后端分离实战项目!我负责后端,狗哥负责前端!
目的就是让大家通过项目实战,学到一些真东西,将所学理论落地,助力有心强大的你更快的成长!开启你的工作之旅,让开发游刃有余!
详细的后端规划和后端大纲思维导图在开篇已经给出,你可以到开篇查收:基于SpringBoot+SpringCloud+Vue前后端分离项目实战 --开篇。
一、创建SpringBoot项目
因为我们已经创建Maven项目:tg-book-web,所以基于此,创建SpringBoot项目,简单来说只需要3小步
:
① 修改pom.xml:加依赖 spring-boot-starter-web
② 创建启动类:加注解 @SpringBootApplication
③ 创建控制器类:加注解 @RestController
1.1 添加springboot依赖
1). web层增加依赖
在tg-book-web的 pom.xml 增加依赖如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
其它dependency。。。
</dependencies>
2). 父项目统一管理依赖
上面的spring-boot-starter-web
没有定义版本号version
,还记得上文我们说的父项目统一管理依赖
吗?
没错,就是父pom.xml的dependencyManagement
节点,用来统一管理依赖版本。
所以,我们需要在dependencyManagement
节点下增加依赖spring-boot-dependencies
,这里包括SpringBoot为我们定义好的所有依赖。
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<!-- spring boot 版本-->
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- spring boot 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>$spring-boot.version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
其它dependency。。。
</dependencies>
</dependencyManagement>
另外,这里有一个小知识点:统一管理依赖有两种方式,一种是上面这样,另外还可以把parent定义为spring-boot-starter-parent
,实际内部也是依赖spring-boot-dependencies
。综合考虑Maven是单继承,所以建议使用上面spring-boot-dependencies
的方式。
3).Maven刷新依赖
温馨提示
:添加完依赖,别忘了刷新Maven,上文说过了,我再重复一遍!
- 父项目右键-》Maven-》Reload Project
- 父项目右键-》Run Maven-》Reimport
我最喜欢的是在最右侧的Maven选项卡,选中父项目,点上面的刷新图标,如下图:(或者右键Reload Project)
1.2 创建启动类
创建启动类:org.tg.book.ApplicationRunner
,如下图 java包右键菜单->New->Java Class
输入类的全名,包括包名,如下图:
启动类里面只有一个入口main方法,用于项目的启动。
main方法里调用SpringApplication.run
方法,并配上@SpringBootApplication
注解,这样就齐活了,里面做了啥先不用深挖!
package org.tg.book;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApplicationRunner
public static void main(String[] args)
SpringApplication.run(ApplicationRunner.class, args);
1.3 创建控制器类
创建控制器类:org.tg.book.web.controller.BookAdminController
,用于向前端提供API,定义如下:
package org.tg.book.web.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/admin")
public class BookAdminController
@GetMapping("/hello")
public String hello(@RequestParam("name") String name)
return "hello:" + name;
到这,我们就已经定义好了一个GET请求的API,请求路径为:/admin/hello?name=xxx
是不是很容易?除了注解,写的都是入门级的代码,一个API就定义好了,所以用SpringBoot开发API可以说是零门槛,OK,我们先运行起来享受一下吧!
对于这几个注解,先别着急,注解会在下面的【3.1 Spring MVC常用注解】里详解!
1.4 Run 或 Debug
我们直接使用IDEA就可以运行,不需要部署Tomcat!
运行(Run):ApplicationRunner
类的右键菜单Run 'ApplicationRunner....main()'
调试(Debug):ApplicationRunner
类的右键菜单 ``Debug ‘ApplicationRunner…main()’`
控制台Console输出如下就代表启动成功了,默认端口是8080
Tomcat started on port(s): 8080 (http) with context path ''
Started ApplicationRunner in xxx seconds
我们用浏览器测试请求:
http://localhost:8080/admin/hello?name=tian
返回结果正如期望,调用成功!
hello:tian
二、开发图书管理API
上面的/hello API,只是开胃小菜,我们来两个正式点的API:
① GET 请求:根据id获取图书
路径:/admin/book;入参:图书id;返回:图书对象
② POST 请求:新增/修改图书
路径:/admin/book;入参:图书对象;返回:图书id
说明:
包结构对应如下图,先上代码,再逐块讲解!
2.1 web层
BookAdminController
- getBook方法:Get请求
- saveBook方法:Post请求
- web层会调用service层,所以依赖注入了BookService
- 注解会在下面的【3.1 Spring MVC常用注解】里详解!
package org.tg.book.web.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.tg.book.common.dto.TgResult;
import org.tg.book.service.BookService;
import org.tg.book.service.bo.BookBO;
import org.tg.book.web.vo.BookVO;
@RestController
@RequestMapping("/admin")
public class BookAdminController
@Autowired
private BookService bookService;
@GetMapping("/book")
public TgResult<BookBO> getBook(@RequestParam("id") Integer id)
return TgResult.ok(bookService.getBook(id));
@PostMapping("/book")
public TgResult<Integer> saveBook(@RequestBody BookVO bookVO)
return TgResult.ok(bookService.saveBook(bookVO.toBookBO()));
BookVO
web层对象,即前端传入的对象!关于各层对象,会在【3.3各层对象说明】详解
package org.tg.book.web.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.tg.book.service.bo.BookBO;
import java.io.Serializable;
import java.util.Date;
@Data
public class BookVO implements Serializable
private Integer id;
private String bookName;
private String bookNo;
private String bookAuthor;
private Integer bookType;
private String bookDesc;
private String publisher;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date publishDate;
public BookBO toBookBO()
BookBO bookBO = new BookBO();
BeanUtils.copyProperties(this, bookBO);
return bookBO;
2.2 service层
BookService
定义service接口:
package org.tg.book.service;
import org.tg.book.service.bo.BookBO;
public interface BookService
BookBO getBook(Integer id);
Integer saveBook(BookBO bookBO);
BookServiceImpl
实现service方法:service层会调用dal层,所以依赖注入了BookMapper
package org.tg.book.service.impl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.tg.book.dal.mapper.BookMapper;
import org.tg.book.dal.po.Book;
import org.tg.book.service.BookService;
import org.tg.book.service.bo.BookBO;
@Service
public class BookServiceImpl implements BookService
@Autowired
private BookMapper bookMapper;
@Override
public BookBO getBook(Integer id)
Book book = bookMapper.selectByPrimaryKey(id);
if (book == null)
return null;
BookBO bookBO = new BookBO();
BeanUtils.copyProperties(book, bookBO);
return bookBO;
@Override
public Integer saveBook(BookBO bookBO)
if (bookBO == null)
return null;
Book book = new Book();
BeanUtils.copyProperties(bookBO, book);
if (bookBO.getId() == null)
return bookMapper.insert(book);
else
return bookMapper.updateByPrimaryKey(book);
BookBO
service层对象
package org.tg.book.service.bo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class BookBO implements Serializable
private Integer id;
private String bookName;
private String bookNo;
private String bookAuthor;
private Integer bookType;
private String bookDesc;
private String publisher;
private Date publishDate;
2.3 dal层
BookMapper
定义数据访问接口:
package org.tg.book.dal.mapper;
import org.tg.book.dal.po.Book;
public interface BookMapper
Book selectByPrimaryKey(Integer id);
Integer insert(Book book);
Integer updateByPrimaryKey(Book book);
BookMapperImpl
数据访问实现类,这里没有保存到数据库,因为还没有讲,所以直接保存在内存List中,当我们集成Mybatis时会改造这块代码。
package org.tg.book.dal.mapper.impl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;
import org.tg.book.dal.mapper.BookMapper;
import org.tg.book.dal.po.Book;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Repository
public class BookMapperImpl implements BookMapper
private final List<Book> bookList = new ArrayList<>();
@Override
public Book selectByPrimaryKey(Integer id)
return bookList.stream().filter(p -> p.getId().equals(id)).findFirst().orElse(null);
@Override
public Integer insert(Book book)
book.setId(bookList.size() + 1);
bookList.add(book);
return book.getId();
@Override
public Integer updateByPrimaryKey(Book book)
Optional<Book> first = bookList.stream().filter(p -> p.getId().equals(book.getId())).findFirst();
if (first.isPresent())
BeanUtils.copyProperties(book, first.get());
return book.getId();
return null;
Book
持久化对象,与数据库表字段对应
package org.tg.book.dal.po;
import lombok.Data;
import java.util.Date;
@Data
public class Book
private Integer id;
private String bookName;
private String bookNo;
private String bookAuthor;
private Integer bookType;
private String bookDesc;
private String publisher;
private Date publishDate;
2.4 Postman测试
最终实现了两个API,可以先对号入座!
三、庖丁解牛API实现
上面只贴了代码,相信大家肯定会有疑问,那下面我们就来一一化解!
3.1 Spring MVC 常用注解
接下来说说如下图中这几个注解的作用。
- 1) @RestController
表示用于处理web请求的控制器
。我们开发前后端分离的Restful风格API,使用@RestController就对了。
关于@RestController经常拿来与@Controller做区别和联系,所以简单说明一下:
@Controller
也表示用于处理web请求的控制器,返回的是视图,配合视图解析器才能返回到指定页面,当需要直接返回数据时需要配合加@ResponseBody注解。
@ResponseBody
表示返回的是数据对象,而不经过视图解析器。
@RestController 等同于@Controller + @ResponseBody,这样我们开发Restful API就方便了,因为我们就是直接返回数据对象,像普通文本、JSON、XML等等对象,所以开发Restful风格的前后端分离项目通常都会用@RestController。
- 2) @RequestMapping
用于处理请求映射
,就是定义请求路径,可以作用于类和方法上。
value
以上是关于天狗实战SpringBoot API开发详解 --SpringMVC注解+封装结果+支持跨域+打包(下)的主要内容,如果未能解决你的问题,请参考以下文章
FFHArkUI Service Ability开发实战详解
SpringBoot--实战开发--OAuth2.0密码模式(五十一)
❤️高级JAVA开发必备技能❤️java8 新日期时间API(JSR-310:实战+源码分析),5万字详解(JAVA 小虚竹,建议收藏)