现在开始我们需要学习一下Spring boot 和Vue3的前后端分离,增强全栈能力
关于Spring Boot 我们需要掌握的有很多东西,比如AOP、拦截器、过滤器、异步化、定时任务、websocket、多环境、缓存,消息队列等等
开发环境有下面这些:
- ideaIU-2019.2.3.exe
- Mysql8.0 / 5.7
- Git-2.23.0-64-bit.exe
- node-v12.10-0-x64.msi
- jdk-8u221-windows-x64.exe / jdk-8u202-linux-x64.tar.gz
Spring Boot项目搭建
1. 两种方法创建Spring Boot
第一种方法就是到官网https://start.spring.io/ 去选择,然后下载到本地,解压后使用IDEA打开就行。
第二种方法就是打开IDEA然后创建一个spring项目,整个流程和你在官网选择几乎一样,但是IDEA2021没有创建spring boot项目这个选择。
2. Spring Boot目录结构

- mvn-> wrapper:这个文件的好处就是你不需要提前去下载maven,但是我们一般本地环境用IDEA自带的Maven就可以了。
- mvnw和mvnw.cmd都是和前面的mvn是一起的,前者是linux命令,后者是windows命令
- src -> resources: 这里放的是一些前端的文件,js,css,如果是前后端分离的话一般用不到,可以将static和templates直接删掉
- application.properties:spring boot的配置文件,我们后面还会仔细讲
- HELP.md:功能类似于README.md
- pom.xml:maven项目依赖文件
3. 启动Spring Boot项目
启动项目可以直接找到Application文件,然后右键运行即可
@SpringBootApplicationpublic class WikiApplication {public static void main(String[] args) {SpringApplication.run(WikiApplication.class, args);}}
4. 总结知识点
- SpringBoot不需要配置容器,是因为使用了嵌入式容器,可以在包当中看到项目本身有org.apache.tomcat.embed,所以也是默认使用tomcat启动。也可以使用传统的方式,打包成war包,放在单独的tomcat当中也是可以的。
- SpringBoot的启动函数需要添加@SpringBootApplication注解
项目初始配置
1. 编码配置
2. JDK配置
在File -> Project Structure当中选择项目的Project SDK
3. Maven配置
因为使用IDEA打开项目之后就会去自动下载依赖,想要使用maven下载的快就要设置settings当中的Maven当中的User settings file选项,并且在配置好后点击后面的Override。我这里的值为:C:\Users\Administrator.m2\settings.xml,这个settings.xml是需要自己创建的,内容如下;
<?xml version="1.0" encoding="UTF-8"?><settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"><!--本地仓库位置--><localRepository>C:\Users\Administrator\.m2\repository</localRepository><pluginGroups/><proxies/><servers></servers><mirrors><!--阿里云的镜像--><mirror><id>alimaven</id><name>aliyun maven</name><url>http://maven.aliyun.com/nexus/content/groups/public/</url><mirrorOf>central</mirrorOf></mirror><!--中央仓库在中国的位置--><mirror><id> maven-net-cn</id><name> Maven China Mirror</name><url> http://maven.net.cn/content/groups/public/</url><mirrorOf>central</mirrorOf></mirror></mirrors><profiles><!--配置jdk的版本--><profile><id>jdk-1.8</id><activation><activeByDefault>true</activeByDefault><jdk>1.8</jdk></activation><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion></properties></profile></profiles></settings>
4. Git配置
- VCS -> Enable Version Control Intergration -> 选择Git
- 在下方找到Git窗口,这里有所有信息,关于操作我们在IDEA项目实战当中已经讲解过,这里就不过多赘述。
5. 关联远程仓库
在github上创建一个新的项目,但是不需要README.md和.gitignore文件,然后回到本地项目当中,在命令行中输入:
- git remote add origin git@gitee.com:taopoppy/wiki.git(这是我的项目地址)
- git push -u origin master
这样就将本地项目和远程项目关联在了一起,前提是远程git仓库设置SSH秘钥,这个在IDEA项目实战当中已经讲述。
比如我们删除掉.gitignore当中的HELP.md选项,那么想要将HELP.md添加到版本管理,可以先Commit面板当中先刷新,然后将HELP.md文件右键选择add to VCS,然后在选择Commit或者Commit and push
启动日志优化
1. logback日志样式修改
在resources文件夹当中添加logback-spring.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?><configuration><!-- 修改一下路径--><property name="PATH" value="./log"></property><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><!-- <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %blue(%-50logger{50}:%-4line) %thread %green(%-18X{LOG_ID}) %msg%n</Pattern>--><Pattern>%d{ss.SSS} %highlight(%-5level) %blue(%-30logger{30}:%-4line) %thread %green(%-18X{LOG_ID}) %msg%n</Pattern></encoder></appender><appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${PATH}/trace.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><FileNamePattern>${PATH}/trace.%d{yyyy-MM-dd}.%i.log</FileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><layout><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-50logger{50}:%-4line %green(%-18X{LOG_ID}) %msg%n</pattern></layout></appender><appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${PATH}/error.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><FileNamePattern>${PATH}/error.%d{yyyy-MM-dd}.%i.log</FileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><layout><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-50logger{50}:%-4line %green(%-18X{LOG_ID}) %msg%n</pattern></layout><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><root level="ERROR"><appender-ref ref="ERROR_FILE" /></root><root level="TRACE"><appender-ref ref="TRACE_FILE" /></root><root level="INFO"><appender-ref ref="STDOUT" /></root></configuration>
修改
2. 增加启动成功日志
我们现在来修改一下启动文件:
@SpringBootApplicationpublic class WikiApplication {private static final Logger LOG = LoggerFactory.getLogger(WikiApplication.class);public static void main(String[] args) {SpringApplication app = new SpringApplication(WikiApplication.class);Environment env = app.run(args).getEnvironment();LOG.info("启动成功");LOG.info("地址:\thttp://127.0.0.1:{}", env.getProperty("server.port"));}}
其中我们需要在application.properties当中书写下面的代码:
server.port=8080
这样说来,env.getProperty这个方法就是用来读取application.properties的某个属性的方法。
3. 修改启动图案
直接在resources文件夹当中添加banner.txt文件,然后在http://patorjk.com/software/taag/#p=display&f=Big&t=taopoppy当中选择你需要的好看的图案,然后保存到banner.txt文件当中。
编写和测试接口
1. hello world接口
我们在前后端分离的项目当中一定要在controller当中书写类,在类中书写接口,比如在src/java/com.taopoppy.wiki/controller/TestController.java当中:
@RestControllerpublic class TestController {@GetMapping("/hello")// @PutMapping// @DeleteMapping// @PostMapping// @RequestMapping(value = "user/1", method = RequestMethod.GET)public String hello() {return "Hello World";}}
- @RestController 这个注解是表示返回的是字符串或者JSON对象
- @GetMapping表示该结构只能由get方法访问,同理@PutMapping、@DeleteMapping、@PostMapping都是如此
- @RequestMapping()这个方法有两个参数,如果直接书写@RequestMapping(“/hello”)表示这个方法支持所有请求方式,但是@RequestMapping(value = “hello”, method = RequestMethod.GET)和@GetMapping(“/hello”)是一样的效果。
2. 修改启动位置
注意正常的启动文件会有@SpringBootApplication这样一个注解,表示启动注解,源码当中它是包含@ComponentScan的注解,这个是扫描的意思,启动类会自动扫描当前启动类所在的文件,将里面的接口文件全部扫描到。
但是现在如果直接把启动文件放在这样的一个位置,如下图:
那么WikiApplication实际上扫描不到TestController这个接口类的,因为不在一个文件内,所以要想让WikiApplicaiton扫描到接口文件就要修改@ComponentScan的扫描范围,因为config文件夹和controller文件夹都在com.taopoppy.wiki当中,所以书写@ComponentScan(“com.taopoppy”)或者@ComponentScan(“com.taopoppy.wiki”)都是可以的。
@ComponentScan("com.taopoppy")@SpringBootApplicationpublic class WikiApplication {private static final Logger LOG = LoggerFactory.getLogger(WikiApplication.class);public static void main(String[] args) {SpringApplication app = new SpringApplication(WikiApplication.class);Environment env = app.run(args).getEnvironment();LOG.info("启动成功");LOG.info("地址:\thttp://127.0.0.1:{}", env.getProperty("server.port"));}}
如果扫描多个包可以这样书写:
@ComponentScan("com.taopoppy","com.test")
配置文件介绍
1. 默认支持的配置文件
spring boot的配置项是在resources当中,但是下面三种都是可以的,只不过写法不同
- resources/application.properties
- resources/config/application.properties
- resources/application.yml
两种不同的文件写法不一样,可以在https://toyaml.com/index.html进行转换:
2. 自定义配置项
自定义配置项就是在application.properties当中书写自己的一些自定义的配置项,然后在其他地方可以直接使用,比如我们在application.properties当中去书写一个这样的代码:
author.name=taopoppy
然后在代码当中可以这样使用:
@RestControllerpublic class TestController {@Value("${author.name: xiaoming}")private String name; // 通过@Value注解拿到author.name的值taopoppy,如果我们没有配置就取默认值xiaoming@GetMapping("/hello")public String hello() {return name; // 作为接口结果返回出去}}
集成热部署
1. 添加依赖
在pom.xml当中添加下面的代码,不需要带版本号,因为这个是spring内置的一个模块:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency>
2. 开启静态编译
3. 开启动态编译
双击Shift进行搜索,搜索Registry,找到下面的图标,在红色方框处勾选即可。
这样我们在修改文件的时候,随时进行修改后,点击Ctrl+S或者Ctrl+F9(工具栏的小锤子按钮:Build project),项目就已经重新热启动了,速度要比自己重启快很多。
IDEA关联数据库
mysql和navicat的安装这里就不多说了,安装好之后,我们使用navicat连接好mysql之后,新建一个数据库,注意要选择utf8mb4,这个是真正的utf8,可以存放表情符号:
1. 新建用户
接下来我们要创建一个专属访问wiki这个数据库的用户,因为root的权限太大了,并不安全。

上面我输入的密码是123456,然后我们在配置一下权限
然后返回到用户界面就可以看到wiki@localhost这个新的用户了,接着使用这个新的用户去连接本地的数据库,点击新建:
2. 新建表


然后在点击保存后输入表名test即可,这样我们就新建了一个test的表。
3. 阿里云数据库的准备
在阿里云的产品-> 数据库-> 云数据库 RDS MySql版,点击立即购买:

然后下一步的实例配置基本不用动,为默认配置,然后下单支付即可,但是要注意的是:后续还要购买服务器ECS,ECS和RDS之间的访问要配置成内网访问,需要购买在同一个地域
- 接着我们进入到阿里云控制台首页
- 找到产品与服务
- 在最近使用产品当中找到云数据库 RDS版
- 进入之后,在左边侧边栏当中找到实例列表,并在最上面导航栏里选择你刚买的RDS的地域,我买的是华北5(呼和浩特)
- 然后显示出实例后,我们点击实例最右侧的管理
- 进入后在左侧边栏当中选择账号管理,然后选择创建账号
- 数据库账号:wiki
- 账号类型:普通账号
- 密码:tao3941319=-=
- 然后在左侧边栏当中选择数据库管理,然后点击创建数据库:
- 数据库(DB)名称:wiki
- 支持字符集:utf8
- 授权账号:wiki(普通账号)
- 账号类型:读写
- 然后在上面找到登录数据库,输入上面我们创建的数据库账号和密码,然后测试连接即可
测试成功之后,我们回到实例,点击实例一栏最左侧的地址,进入之后有两个地址
如果能从IDEA当中的plugins搜到最好,搜不到就要手动下载,我们去IDEA插件网搜索Database Navigator,下载下来,都放在G:\javaplugin当中,然后在IDEA的plugins配置当中去加载这个插件。
- 然后需要驱动mysql-connector-java,所以我们到https://mvnrepository.com/去搜索,然后将对应的代码放在pom.xml当中,会自动到我们前面配的阿里云上拉取这个jar包(所有版本,除非你自己指定版本),我在IDEA当中配的是D:\apache-maven-3.8.1\maven-repo,默认是在C:\Users\Administrator.m2\repository
然后在view -> Tools Windows ->DB Browser,然后创建一个新的,特别注意我们这里只是配置了本地的,如果你配置阿里云的话,Host就要填外网地址。<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>


友情提示,在阿里云外网地址和内网地址默认是显示不出来的,必须先要设置白名单,白名单默认是127.0.0.1,即禁止一切其他访问,变成0.0.0.0/0才能允许其他一切访问。
集成Mybatis
1. 集成mybatis
简单的说:和数据库打交道的这一层就是持久层,常见的持久层有Mybatis、Hibernate、前者是半自动的,后者是全自动,半自动就是需要自己写sql,全自动就是不需要写sql。我们首先在pom.xml添加依赖:
<!--集成mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency><!--集成mysql连接--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.22</version></dependency>
添加了mybatis,我们需要到application.properties当中去配置数据源:
# 增加数据库连接spring.datasource.url=jdbc:mysql://rm-hp3f05153598ck3e5vo.mysql.huhehaote.rds.aliyuncs.com/wiki?characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghaispring.datasource.username=wikispring.datasource.password=***** # 这里是我自己的密码spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2. 使用mybatis
特别注意:集成mybatis只需要下载jar包以及配置数据源,并不会真正去连接你配置的数据源,所以你即使是配错了也无所谓。那接下来我们看一下怎么使用:
(1)domain(实体类)
- 在com.taopoppy.wiki下面新建一个domain的package(这一层实体类就是和数据库表一一映射)
- 在domain下面新建一个Test的class实体类,内容如下 ```java package com.taopoppy.wiki.domain;
public class Test { private Integer id;
private String name;private String password;// 下面代码直接右键Genetater->Getter and Setter生成public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}
<br /><a name="A702R"></a>#### (2)mapper(持久层)**持久层叫Mapper层,即广为人知的Dao层,因为后续要用官方代码生成器,其生成的代码就是XXXMapper**<br />所以我们现在来写一个接口:- 在com.taopoppy.wiki下面新建一个mapper的package- 在mapper下面新建一个interface:TestMapper,内容如下:```javapackage com.taopoppy.wiki.mapper;import com.taopoppy.wiki.domain.Test;import java.util.List;public interface TestMapper {public List<Test> list();}
然后我们去书写关于sql的xml文件:
- 在resources下面创建mapper文件夹
在mapper文件夹下面创建一个TestMapper.xml的文件,其中使用到了mybatis的语法: ```xml <?xml version=”1.0” encoding=”UTF-8” ?> <!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd“ >
接着我们需要做两个配置,因为你写了mapper和xml的sql,但是项目不认识:- 在config/WikiApplication当中配置扫描mapper持久层文件```java@ComponentScan("com.taopoppy")@SpringBootApplication@MapperScan("com.taopoppy.wiki.mapper") # 这里配置public class WikiApplication {private static final Logger LOG = LoggerFactory.getLogger(WikiApplication.class);public static void main(String[] args) {SpringApplication app = new SpringApplication(WikiApplication.class);Environment env = app.run(args).getEnvironment();LOG.info("启动成功");LOG.info("地址:\thttp://127.0.0.1:{}", env.getProperty("server.port"));}}
在resources/application.properties当中配置mybatis的xml路径,其中classpath就是resources,/*/.xml表示mapper文件夹下的所有xml文件。
# 配置mybatics所有Mapper.xml所在的路径mybatis.mapper-locations=classpath:/mapper/**/*.xml
(3)service(服务层)
在com.taopoppy.wiki下面新建一个service的package
- 在service下面创建一个Class叫做:TestService,代码如下: ```java package com.taopoppy.wiki.service;
import com.taopoppy.wiki.domain.Test; import com.taopoppy.wiki.mapper.TestMapper; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import java.util.List;
@Service public class TestService { @Resource private TestMapper testMapper;
public List<Test> list() {return testMapper.list();}
}
<a name="G1Kof"></a>#### (4)controller(控制层)最后我们就要在controller这个包下面创建:TestController,内容如下:```javapackage com.taopoppy.wiki.controller;import com.taopoppy.wiki.domain.Test;import com.taopoppy.wiki.service.TestService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.util.List;@RestControllerpublic class TestController {@Resourceprivate TestService testService;@GetMapping("/test/list")public List<Test> list() {return testService.list();}}
整个接口调用的顺序是:
- controller -> service ->mapper -> resources/mapper
此时,可以正常调用http://127.0.0.1:8081/test/list
Mybatis Generator使用
1. mybatis generator的集成
通过上面的代码可以看出来,写一个接口实在是太麻烦,然后我们可以使用mybitis的官方生成器,首先在pom.xml当中去粘贴下面的代码到plugins处:
<!-- mybatis generator 自动生成代码插件 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.0</version><configuration><configurationFile>src/main/resources/generator/generator-config.xml</configurationFile><overwrite>true</overwrite><verbose>true</verbose></configuration><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.22</version></dependency></dependencies></plugin>
然后我们要自己生成一个src/main/resources/generator/generator-config.xml文件,注意复制粘贴后需要修改对应的东西:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><context id="Mysql" targetRuntime="MyBatis3" defaultModelType="flat"><!-- 自动检查关键字,为关键字增加反引号 --><property name="autoDelimitKeywords" value="true"/><property name="beginningDelimiter" value="`"/><property name="endingDelimiter" value="`"/><!--覆盖生成XML文件--><plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" /><!-- 生成的实体类添加toString()方法 --><plugin type="org.mybatis.generator.plugins.ToStringPlugin"/><!-- 不生成注释 --><commentGenerator><property name="suppressAllComments" value="true"/></commentGenerator><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://rm-hp3f05153598ck3e5vo.mysql.huhehaote.rds.aliyuncs.com:3306/wikidev?serverTimezone=Asia/Shanghai"userId="wikidev"password="tao3941319=-="></jdbcConnection><!-- domain类的位置 --><javaModelGenerator targetProject="src\main\java"targetPackage="com.taopoppy.wiki.domain"/><!-- mapper xml的位置 --><sqlMapGenerator targetProject="src\main\resources"targetPackage="mapper"/><!-- mapper类的位置 --><javaClientGenerator targetProject="src\main\java"targetPackage="com.taopoppy.wiki.mapper"type="XMLMAPPER"/><table tableName="demo" domainObjectName="Demo"/></context></generatorConfiguration>
注意:上述文件当中的table里面写的demo,前提我们要在连接的数据库当中提前创建好这个demo的表。后面生成的文件全是关于这个demo表的,如果生成其他相关表的代码就要改这里的tableName的值。
在启动符号的左边下拉框当中找到:Edit Configurations,然后新增一个maven的configuration:
然后我们去执行一下这个configuration:
接着就会创建出响应的代码,在domain生成了Demo.java和DemoExample.java,在mapper下面生成了DemoMapper,在resources/mapper下面生成了DemoMapper.xml。请注意:这四个文件我们以后都不要动
2. mybatis generator的使用
现在我们先在sercvice下面创建一个DemoService文件,内容如下:
package com.taopoppy.wiki.service;import com.taopoppy.wiki.domain.Demo;import com.taopoppy.wiki.mapper.DemoMapper;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.util.List;@Servicepublic class DemoService {@Resourceprivate DemoMapper demoMapper;public List<Demo> list() {// 传null表示查所有的表数据return demoMapper.selectByExample(null);}}
然后在controller当中创建DemoController.java,内容如下:
package com.taopoppy.wiki.controller;import com.taopoppy.wiki.domain.Demo;import com.taopoppy.wiki.service.DemoService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.util.List;@RestController@RequestMapping("/demo")public class DemoController {@Resourceprivate DemoService demoService;@GetMapping("/list")public List<Demo> list() {return demoService.list();}}
这样的话,我们就可以在http/demo.http文件下书写这样的请求去测试:
GET http://localhost:8081/demo/list
统一规范
1. 电子书列表查询开发
先执行一下下面的代码,在ebook表创造点数据:
drop table if exists `ebook`;create table `ebook` (`id` bigint not null comment 'id',`name` varchar(50) comment '名称',`category1_id` bigint comment '分类1',`category2_id` bigint comment '分类2',`description` varchar(200) comment '描述',`cover` varchar(200) comment '封面',`doc_count` int comment '文档数',`view_count` int comment '阅读数',`vote_count` int comment '点赞数',primary key (`id`)) engine=innodb default charset=utf8mb4 comment='电子数';insert into `ebook` (id, name, description) values (1, 'Spring Boot 入门教程','零基础入门Java开发,企业级应用开发最佳首选框架');insert into `ebook` (id, name, description) values (2, 'Vue 入门教程','零基础入门 Vue 开发,企业级应用开发最佳首选框架');insert into `ebook` (id, name, description) values (3, 'Python 入门教程','零基础入门 Python 开发,企业级应用开发最佳首选框架');insert into `ebook` (id, name, description) values (4, 'Mysql 入门教程','零基础入门 Mysql 开发,企业级应用开发最佳首选框架');
然后我们修改generator-config.xml文件,修改最下面的table标签:
然后回到上面去执行一下我们之前生成的名字叫做mybatis-generator的configration,生成ebook相关的持久层代码。
然后就去书写service和controller层的代码(直接粘贴复制以前的代码,然后对应的关键词修改成为ebook或者Ebook即可):
package com.taopoppy.wiki.service;import com.taopoppy.wiki.domain.Ebook;import com.taopoppy.wiki.mapper.EbookMapper;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.util.List;@Servicepublic class EbookService {@Resourceprivate EbookMapper ebookMapper;public List<Ebook> list() {// 传null表示查所有的表数据return ebookMapper.selectByExample(null);}}
package com.taopoppy.wiki.controller;import com.taopoppy.wiki.domain.Ebook;import com.taopoppy.wiki.service.EbookService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.util.List;@RestController@RequestMapping("/ebook")public class EbookController {@Resourceprivate EbookService ebookService;@GetMapping("/list")public List<Ebook> list() {return ebookService.list();}}
然后我们去http/ebook.http当中测试GET http://localhost:8081/ebook/list即可
由于后端会有很多接口,为了让前端能够统一处理逻辑(比如登录校验,权限校验),需要统一后端的返回值,所以我们需要自己制作一个统一的类,在com.taopoppy.wiki.resp的CommonResp内容如下:
package com.taopoppy.wiki.resp;public class CommonResp<T> {/*** 业务上的成功或失败*/private boolean success = true;/*** 返回信息*/private String message;/*** 返回泛型数据,自定义类型*/private T content;public boolean isSuccess() {return success;}public void setSuccess(boolean success) {this.success = success;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getContent() {return content;}public void setContent(T content) {this.content = content;}}
然后我们在EbookController返回值当中就可以这样写(特别要注意泛型):
@GetMapping("/list")public CommonResp list() {CommonResp<List<Ebook>> resp = new CommonResp<>();List<Ebook> list = ebookService.list();resp.setContent(list);return resp;}
2. 封装请求参数和返回参数
我们先来做一个模糊查询的功能,比如我们在EbookController.java当中修改一下代码:
@GetMapping("/list")public CommonResp list(String name) { # 传递name参数进去CommonResp<List<Ebook>> resp = new CommonResp<>();List<Ebook> list = ebookService.list(name);resp.setContent(list);return resp;}
接着修改EbookService.java当中的代码:
public List<Ebook> list(String name) {// 创建一个Ebookexample的查询实例EbookExample ebookExample = new EbookExample();// createCriteria相当于where条件EbookExample.Criteria criteria = ebookExample.createCriteria();criteria.andNameLike("%" + name + "%");// 根据ebookExample条件查询return ebookMapper.selectByExample(ebookExample);}
接着我们可以通过GET http://localhost:8081/ebook/list?name=Spring 这种方式进行模糊查询
但是由于我们还有其他参数需要传递,所以我们不可能每一个参数都要书写一遍,所以我们需要将请求参数封装成一个类,另外我们之前书写的Ebook类是和数据库一一对应的,比如说如果是用户登录,我们不能将User当中的所有属性返回,因为密码也在里面,所以应该只将部分属性返回,也就必须创建一个返回类:
- EbookReq(用户请求的类)——-> Ebook(数据库对应的实体类)———-> EbookResp(服务器返回的类)
所以我们先创建req这个包,然后创建EbookReq.java,从用户的请求来看,只有可能需要传递id和name两个参数,所以内容如下(实际是拿Ebook类来做了剔除的工作):
package com.taopoppy.wiki.req;public class EbookReq {private Long id;private String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();sb.append(getClass().getSimpleName());sb.append(" [");sb.append("Hash = ").append(hashCode());sb.append(", id=").append(id);sb.append(", name=").append(name);sb.append("]");return sb.toString();}}
然后我们接着创建resp这个包,在此包下创建EbookResp这个类,这个类实际就是拷贝Ebook类,因为这个类的所有属性都可以暴露给用户,所以这里就不展示了。
然后我们EbookController文件就需要改一下了,这个时候返回的就是EbookResp的类型:
@RestController@RequestMapping("/ebook")public class EbookController {@Resourceprivate EbookService ebookService;@GetMapping("/list")public CommonResp list(EbookReq req) {// controller层尽量不要出现Ebook这个实体类// 因为实体类是和数据库一一对应的CommonResp<List<EbookResp>> resp = new CommonResp<>();List<EbookResp> list = ebookService.list(req);resp.setContent(list);return resp;}}
与此同时,我们要将从数据库查出的Ebook类型全部转换为EbookResp类型,所以EbookService.java内容如下:
@Servicepublic class EbookService {@Resourceprivate EbookMapper ebookMapper;public List<EbookResp> list(EbookReq req) {EbookExample ebookExample = new EbookExample();// createCriteria相当于where条件EbookExample.Criteria criteria = ebookExample.createCriteria();criteria.andNameLike("%" + req.getName() + "%");// 根据ebookExample条件查询List<Ebook> ebooksList = ebookMapper.selectByExample(ebookExample);// 通过循环将通过Ebook类型查询的数据库数据 转换为 EbookResp类型数据转化出去List<EbookResp> respList = new ArrayList<>();for (Ebook ebook : ebooksList) {EbookResp ebookResp = new EbookResp();// 使用BeanUtils.copyProperties方法把对象属性拷贝到另一个里面BeanUtils.copyProperties(ebook, ebookResp);respList.add(ebookResp);}return respList;}}
3. 制作CopyUtil封装BeanUtils
通过上面的代码可以看到,对于Ebook和EbookResp转换的代码实际在后续很多地方都能用到,所以我们决定将其进行封装,创建一个util的包,然后创建CopyUtil.java,内容如下:
package com.taopoppy.wiki.util;import org.springframework.beans.BeanUtils;import org.springframework.util.CollectionUtils;import java.util.ArrayList;import java.util.List;public class CopyUtil {/*** 单体复制*/public static <T> T copy(Object source, Class<T> clazz) {if (source == null) {return null;}T obj = null;try {obj = clazz.newInstance();} catch (Exception e) {e.printStackTrace();return null;}BeanUtils.copyProperties(source, obj);return obj;}/*** 列表复制*/public static <T> List<T> copyList(List source, Class<T> clazz) {List<T> target = new ArrayList<>();if (!CollectionUtils.isEmpty(source)){for (Object c: source) {T obj = copy(c, clazz);target.add(obj);}}return target;}}
上面的代码可以直接复制粘贴,因为是通用的,这样我们之前书写的代码就可以一行代替:
public List<EbookResp> list(EbookReq req) {EbookExample ebookExample = new EbookExample();// createCriteria相当于where条件EbookExample.Criteria criteria = ebookExample.createCriteria();criteria.andNameLike("%" + req.getName() + "%");// 根据ebookExample条件查询List<Ebook> ebooksList = ebookMapper.selectByExample(ebookExample);// // 通过循环将通过Ebook类型查询的数据库数据 转换为 EbookResp类型数据转化出去// List<EbookResp> respList = new ArrayList<>();// for (Ebook ebook : ebooksList) {// // EbookResp ebookResp = new EbookResp();// // // 使用BeanUtils.copyProperties方法把对象属性拷贝到另一个里面// // BeanUtils.copyProperties(ebook, ebookResp);//// EbookResp ebookResp = CopyUtil.copy(ebook, EbookResp.class);//// respList.add(ebookResp);// }// 上面10-20的代码直接代替为这一行List<EbookResp> respList = CopyUtil.copyList(ebooksList, EbookResp.class);return respList;}
小技巧:如果代码改动了,但是出现莫名的错,可以试一下maven clean,比如:
- 代码没错却编译出错
- 测试结果和代码不符
- 引入了jar包却没有反应

