后端架构完善与接口开发

数据库准备

数据库的创建,选择名为wiki,排序规则为:utf8mb4 --UTF-8 Unicode

1
2
3
4
5
6
7
8
DROP TABLE IF EXIT `test`;
CREATE TABLE `test`(
`id` BIGINT NOT NULL COMMENT 'id',
`name` VARCHAR(50) COMMENT '名称',
`password` VARCHAR(50) COMMENT '密码',
PRIMARY KEY (`id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='测试';

IDEA数据库插件配置

集成持久层框架Mybatis

1.名词

  • 持久层
  • ORM

2.集成Mybatis

配置数据源

  • 引入依赖:porm.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- 集成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>
  • 增加数据库连接:application.properties

    1
    2
    3
    4
    5
    # 增加数据库连接
    spring.datasource.url=jdbc:mysql://localhost:3306/wiki?characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    spring.datasource.username=root
    spring.datasource.password=*****
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3.使用Mybatis

  • 配置mybatis所有Mapper.xml所在的路径application.properties

    1
    2
    # 配置mybatis所有Mapper.xml所在的路径
    mybatis.mapper-locations=classpath:/mapper/**/*.xml
  • 使用@MapperScan扫描所有的Mapper接口,让其知道wiki.mapper下面的持久层

    • @MapperScan("com.javami.wiki.mapper") 接口和XML的命名
1
2
3
4
5
6
7
8
9
10
@ComponentScan("com.javami")
@SpringBootApplication
@MapperScan("com.javami.wiki.mapper")
public class WikiApplication {
private static final Logger LOG = LoggerFactory.getLogger(WikiApplication.class);
public static void main(String[] args) {
SpringApplication.run(WikiApplication.class, args);
LOG.info("启动成功!!");
}
}

4.关于mapper文件下的xxMapper.xml的解释,id对应xxMapper.java对应的方法名,namespace对应xxMapper.java接口的具体类位置。比如:com.jiawa.wiki.mapper.TestMapper

5.Free Mybatis plugin插件可以做代码跳转

6.使用@Service@RestController注解,将Service类或Controller类交给Spring来管理了。

  • 使用@Resource@Autowire将一个类注入到另一个类中
1
2
3
4
5
6
7
8
9
10
11
12

//将Service类或Controller类交给Spring来管理了
@Service
public class TestService {
//将TestMapper注入进来
@Resource
private TestMapper testMapper;

public List<Test> list() {
return testMapper.list();
}
}

集成Mybatis官方代码生成器

1.如何集成Mybatis Generator

  • 增加插件依赖porm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- 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>
  • resources文件夹下创建generator文件夹增加配置文件generator-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//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-uf6470s9615e13hc4no.mysql.rds.aliyuncs.com:3306/wikidev?serverTimezone=Asia/Shanghai"
userId="wikidev"
password="wikidevABC123">
</jdbcConnection>

<!-- domain类的位置 -->
<javaModelGenerator targetProject="src\main\java"
targetPackage="com.jiawa.wiki.domain"/>

<!-- mapper xml的位置 -->
<sqlMapGenerator targetProject="src\main\resources"
targetPackage="mapper"/>

<!-- mapper类的位置 -->
<javaClientGenerator targetProject="src\main\java"
targetPackage="com.jiawa.wiki.mapper"
type="XMLMAPPER"/>

<!--<table tableName="demo" domainObjectName="Demo"/>-->
<!--<table tableName="ebook"/>-->
<!--<table tableName="category"/>-->
<!--<table tableName="doc"/>-->
<!--<table tableName="content"/>-->
<!--<table tableName="user"/>-->
<table tableName="ebook_snapshot"/>
</context>
</generatorConfiguration>
  • 增加执行命令

2.RequestMapping 注解也可以用在类上面

电子书列表查询接口开发

1.创建ebook表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DROP TABLE IF EXIT `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入门教程',';零基础开发入门,企业级开发最佳框架');

2.配置generator-config.xml,生成Mybatis的mapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//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-uf6470s9615e13hc4no.mysql.rds.aliyuncs.com:3306/wikidev?serverTimezone=Asia/Shanghai"
userId="wikidev"
password="wikidevABC123">
</jdbcConnection>

<!-- domain类的位置 -->
<javaModelGenerator targetProject="src\main\java"
targetPackage="com.jiawa.wiki.domain"/>

<!-- mapper xml的位置 -->
<sqlMapGenerator targetProject="src\main\resources"
targetPackage="mapper"/>

<!-- mapper类的位置 -->
<javaClientGenerator targetProject="src\main\java"
targetPackage="com.jiawa.wiki.mapper"
type="XMLMAPPER"/>

<!--<table tableName="demo" domainObjectName="Demo"/>-->
<!--<table tableName="ebook"/>-->
<!--<table tableName="category"/>-->
<!--<table tableName="doc"/>-->
<!--<table tableName="content"/>-->
<!--<table tableName="user"/>-->
<table tableName="ebook_snapshot"/>
</context>
</generatorConfiguration>

3.配置service层下的EbookService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Service
public class EbookService {

@Resource
private EbookMapper ebookMapper;

public List<EbookResp> list(EbookReq req) {
EbookExample ebookExample = new EbookExample();
EbookExample.Criteria criteria = ebookExample.createCriteria();
if (!ObjectUtils.isEmpty(req.getName())) {
criteria.andNameLike("%" + req.getName() + "%");
}
List<Ebook> ebookList = ebookMapper.selectByExample(ebookExample);

// List<EbookResp> respList = new ArrayList<>();
// for (Ebook ebook : ebookList) {
// // EbookResp ebookResp = new EbookResp();
// // BeanUtils.copyProperties(ebook, ebookResp);
// // 对象复制
// EbookResp ebookResp = CopyUtil.copy(ebook, EbookResp.class);
//
// respList.add(ebookResp);
// }

// 列表复制
List<EbookResp> list = CopyUtil.copyList(ebookList, EbookResp.class);

return list;
}
}

4.配置controller层下的EbookController.java

1
2
3
4
5
6
7
8
9
10
11
@RestController
@RequestMapping("/ebook")
public class EbookController {
@Resource
private EbookService ebookService;

@GetMapping("list")
public List<Ebook> list(){
return ebookService.list();
}
}

5.后端接口统一返回参数,方便前端统一处理

①创建resp文件夹,创建CommonResp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.jiawa.wiki.resp;

public class CommonResp<T> {

/**
* 业务上的成功或失败
*/
private boolean success = true;

/**
* 返回信息
*/
private String message;

/**
* 返回泛型数据,自定义类型
*/
private T content;

public boolean getSuccess() {
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;
}

@Override
public String toString() {
final StringBuffer sb = new StringBuffer("ResponseDto{");
sb.append("success=").append(success);
sb.append(", message='").append(message).append('\'');
sb.append(", content=").append(content);
sb.append('}');
return sb.toString();
}
}

②controller层下修改EbookController.java,使其后端返回统一参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@RequestMapping("/ebook")
public class EbookController {
@Resource
private EbookService ebookService;

@GetMapping("list")
public CommonResp list(){
CommonResp<List<Ebook>> resp = new CommonResp<>();
List<Ebook> list = ebookService.list();
resp.setContent(list);
return resp;
}
}

封装请求参数和返回参数

1.封装请求和返回参数

  • XXXReq
  • XXXResp

①创建req包,创建EbookReq.java文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.javami.wiki.req;

/**
* @author Kevin
* @create 2021-08-03 22:41
*/
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;
}

@Override
public String toString() {
return "EbookReq{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

②创建resp包,EbookResp.java文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package com.javami.wiki.resp;

/**
* @author Kevin
* @create 2021-08-03 22:59
*/
public class EbookResp {
private String name;

private Long category1Id;

private Long category2Id;

private String description;

private String cover;

private Integer docCount;

private Integer viewCount;

private Integer voteCount;


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Long getCategory1Id() {
return category1Id;
}

public void setCategory1Id(Long category1Id) {
this.category1Id = category1Id;
}

public Long getCategory2Id() {
return category2Id;
}

public void setCategory2Id(Long category2Id) {
this.category2Id = category2Id;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getCover() {
return cover;
}

public void setCover(String cover) {
this.cover = cover;
}

public Integer getDocCount() {
return docCount;
}

public void setDocCount(Integer docCount) {
this.docCount = docCount;
}

public Integer getViewCount() {
return viewCount;
}

public void setViewCount(Integer viewCount) {
this.viewCount = viewCount;
}

public Integer getVoteCount() {
return voteCount;
}

public void setVoteCount(Integer voteCount) {
this.voteCount = voteCount;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", name=").append(name);
sb.append(", category1Id=").append(category1Id);
sb.append(", category2Id=").append(category2Id);
sb.append(", description=").append(description);
sb.append(", cover=").append(cover);
sb.append(", docCount=").append(docCount);
sb.append(", viewCount=").append(viewCount);
sb.append(", voteCount=").append(voteCount);
sb.append("]");
return sb.toString();
}
}

②修改controller包下的EbookController.java,让其请求是Ebookreq的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@RequestMapping("/ebook")
public class EbookController {
@Resource
private EbookService ebookService;

@GetMapping("list")
public CommonResp list(EbookReq req){
CommonResp<List<EbookResp>> resp = new CommonResp<>();
List<EbookResp> list = ebookService.list(req);
resp.setContent(list);
return resp;
}
}

②修改service包下的EbookService.java,接受路由传递进来的Ebookreq

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Service
public class EbookService {

@Resource
private EbookMapper ebookMapper;

public List<EbookResp> list(EbookReq req){
EbookExample ebookExample = new EbookExample();
EbookExample.Criteria criteria = ebookExample.createCriteria();
criteria.andNameLike("%"+req.getName()+"%");
List<Ebook> ebookList = ebookMapper.selectByExample(ebookExample);

List<EbookResp> respList = new ArrayList<>();
for(Ebook ebook: ebookList){
EbookResp ebookResp = new EbookResp();
//BeanUtils工具类的使用
BeanUtils.copyProperties(ebook,ebookResp);
respList.add(ebookResp);
}

return respList;
}
}

③测试

1
http://localhost:8880/ebook/list?name=spring

制作CopyUtil封装BeanUtils

1.CopyUtil工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.jiawa.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;
}
}

使用CopyUtil优化service包下的EbookService.java

1
2
3
4
5
6
        for(Ebook ebook: ebookList){
// EbookResp ebookResp = new EbookResp();
// BeanUtils.copyProperties(ebook,ebookResp);
EbookResp ebookResp = CopyUtil.copy(ebook,EbookResp.class);
respList.add(ebookResp);
}

2.如果代码改动了,但是出现莫名其妙的错,可以试一下maven clean,比如:

  • 代码没错却编译出错
  • 测试结果跟代码不符
  • 引入了jar包却没反应

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!