1 单体架构阶段概述和项目展示
- 基于SpringBoot2.x实现单体架构设计与准备工作
- 实现单体电商项目核心功能开发
- 实现单体电商项目个人中心功能
- 项目部署与上线
- 项目演示
- 前后端主要技术选型
- 前后端分离开发模式
- 后端分层架构模式
- 数据库表设计
- Springboot、Spring、Mybatis框架整合
2 前后端技术选型讲解
技术选型SpringBoot vs SpringMVC
- SpringMVC是框架,SpringBoot是工具
- 从配置繁琐(XML)到零配置(yml)
- SpringBoot继承了多样化中间件[*-starter]
-
聊一聊Struts
安全漏洞
- 请求变量共享
- Filter拦截
-
前端技术选型
MVVM开发模式
- Jquery、VUE.js
- html
-
技术选型所需要考虑的事情
切合业务
- 社区活跃度
- 团队技术水平
- 版本更新迭代周期
- 试错精神
- 安全性
- 成功案例
- 开源精神
3 前后端分离开发模式
略4 项目拆分与聚合
如上图,日常生活中有很多汽车生产商,汽车中有很多组件,比如车轮,地盘,座椅,方向盘等,汽车生产商不可能面面俱到都会生产这些组件,通常的做法就是把很多组件外包出去。最后把零件组装。
开发项目的时候其实跟汽车的生产类似,刚开始我们把项目进行拆分分层,最后在运行的时候进行聚合,这样就能降低耦合度。
- Maven聚合项目
现在主流的项目都是使用Maven进行搭建的,此时maven就像汽车生产商,common.jar和pojo.jar相当于每个组件,最后由maven进行打包成war或者jar进行发布部署。
5 构建聚合工程
接下来,我们就来利用SpringBoot搭建一个web工程,体会一下SpringBoot的魅力所在!
5.1 创建maven parent工程
我们先新建一个空的工程:
工程名为java-architects:
新建一个model:
使用maven来构建:
然后填写项目坐标:
目录结构:
项目结构:
打开pom.xml查看有些什么东西。
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chaining</groupId>
<artifactId>foodie-dev</artifactId>
<version>1.0-SNAPSHOT</version>
<!--packaging值有pom,jar和war-->
<packaging>pom</packaging>
</project>
在maven里有一个packaging标签,因为我们现在构建的foodie-dev是一个顶级工程,因此packaging写pom。
5.2创建子工程
右击foodie-dev选择New-Module
此时可以看到Parent中标明了我们的父工程为foodie-dev,我们在ArtifactId中输入foodie-dev-common,创建完成查看目录结构如下:
这里的pom中依然没有给出packaging的打包方式,因为默认打包方式是jar。
此时查看父工程的pom文件,多了下面标签内容
<modules>
<module>foodie-dev-common</module>
</modules>
此时表明foodie-dev中有一个子模块为foodie-dev-common,后面所有的子模块都会出现在这里。
1.聚合工程里可以分为顶级项目(顶级工程、父工程)与子工程,这两者的关系其实就是父子继承的关系
子工程在maven里成为模块(module),模块之间是平级,是可以相互依赖的
2.子模块可以使用顶级工程里所有的子u按(依赖),子模块之间如果要使用资源,必须构建依赖(构建关系)
3.一个顶级工程可以由多个不同的子工程共同组合而成
2.5工程代码:https://github.com/chainingning/java-architects/tree/master
6 构建聚合工程2
根据2.5.2创建foodie-dev-pojo、foodie-dev-mapper,foodie-dev-service,foodie-dev-api,pom如下:
- foodie-dev-pojo
此工程需要使用到common中的方法,因此需要依赖common工程
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>foodie-dev</artifactId>
<groupId>com.chaining</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>foodie-dev-pojo</artifactId>
<dependencies>
<dependency>
<groupId>com.chaining</groupId>
<artifactId>foodie-dev-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
- foodie-dev-mapper
此工程需要使用到pojo中的方法,因此需要依赖pojo工程,pojo又依赖了common,因此mapper通过pojo是可以使用common工程中的方法的。
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>foodie-dev</artifactId>
<groupId>com.chaining</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>foodie-dev-mapper</artifactId>
<!--
mapper依赖了pojo,pojo又依赖了common
mapper通过pojo是可以使用common工程中的方法的
-->
<dependencies>
<dependency>
<groupId>com.chaining</groupId>
<artifactId>foodie-dev-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
foodie-dev-service ```java <?xml version=”1.0” encoding=”UTF-8”?> <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>foodie-dev</artifactId>
<groupId>com.chaining</groupId>
<version>1.0-SNAPSHOT</version>
4.0.0 foodie-dev-service com.chaining foodie-dev-mapper 1.0-SNAPSHOT
- foodie-dev-api
```java
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>foodie-dev</artifactId>
<groupId>com.chaining</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>foodie-dev-api</artifactId>
<dependencies>
<dependency>
<groupId>com.chaining</groupId>
<artifactId>foodie-dev-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
模块依赖说明:
我们互相依赖了很多模块,在install后才可以正常使用!
TIPS:如果在pom里写依赖的时候没有提示,第一查看自己的IDEA版本是否为2019.2,该版本有很多bug,不推荐使用,如果IDEA不是2019.2,查看教程 https://www.yuque.com/chaining/architects/fvktdl
语雀内容
7 PDMan数据库建模工具使用
PDMan http://www.pdman.cn/#/
安装教程和使用参考官方文档http://www.pdman.cn/#/
建议使用PDMan-win64_v2.1.6.exe,最新版(PDMan-win64_v2.2.0.exe)暂时关闭了数据库连接功能
8 生产环境增量与全量脚本迭代
每次数据库的迭代都是增量的迭代,也就是每次数据库的修改都是增量的,点击同步配置
重建数据表:会把表清空后重新执行脚本,生产环境谨慎使用。
正常开发过程中,都使用字段增量
9 数据库物理外键移除原因
外键是否采用,看业务应用场景,以及开发成本的。
- 互联网行业应用
不推荐使用外键, 用户量大,并发高,数据库容易成为性能瓶颈,尤其受IO限制, 此时不用外键,把数据一致性的控制放到程序事务中,易于水平扩展。 传统行业
软件应用的用户数有限,数据量也一般不会超大,且活跃数据有限。综述,即数据库服务器的性能不是问题,不用过多考虑性能问题
分析外键约束的优点与缺点
优点
保证表间保证数据的完整性和一致性,是事务的一致性实现
- 级联操作方便
- 将数据完整性判断托付 给了数据库完成,减少了程序的代码量
-
缺点
性能瓶颈
外键被数据库维护,当涉及外键字段的增,删,更新操作之后,需要触发先关查询去检查,性能开销- 并发死锁
update/delete时,外键对数据一致性的控制,其他表内部加锁。进行行锁操作,在并发大流量事务场景,很容易造成死锁 - 扩展性差
随着数据量的增加 ,分库分表时,外键无法生效,所以将数据关系维护在程序中,方便迁移 - 热更新
分布式环境下,项目经常使用热更新(不停机维护),如果有外键的话,数据库是强一致性,可能导致我们更新的代码不能使用。
- 降低耦合度
10. 重新认识SpringBoot
在这一部分,我们主要了解以下3个问题:
- 什么是SpringBoot
- 为什么要学习SpringBoot
- SpringBoot的特点
10.1 什么是SpringBoot
SpringBoot是Spring项目中的一个子工程,与我们所熟知的Spring-framework 同属于spring的产品:
我们可以看到下面的一段介绍:
Takes an opinionated view of building production-ready Spring applications. Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible.
翻译一下:
用一些固定的方式来构建生产级别的spring应用。Spring Boot 推崇约定大于配置的方式以便于你能够尽可能快速的启动并运行程序。
其实人们把Spring Boot 称为搭建程序的脚手架
。其最主要作用就是帮我们快速的构建庞大的spring项目,并且尽可能的减少一切xml配置,做到开箱即用,迅速上手,让我们关注与业务而非配置。
10.2.为什么要学习SpringBoot
java一直被人诟病的一点就是臃肿、麻烦。当我们还在辛苦的搭建项目时,可能Python程序员已经把功能写好了,究其原因注意是两点:
- 复杂的配置,
项目各种配置其实是开发时的损耗, 因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以写配置挤占了写应用程序逻辑的时间。 - 一个是混乱的依赖管理。
项目的依赖管理也是件吃力不讨好的事情。决定项目里要用哪些库就已经够让人头痛的了,你还要知道这些库的哪个版本和其他库不会有冲突,这难题实在太棘手。并且,依赖管理也是一种损耗,添加依赖不是写应用程序代码。一旦选错了依赖的版本,随之而来的不兼容问题毫无疑问会是生产力杀手。
而SpringBoot让这一切成为过去!
Spring Boot 简化了基于Spring的应用开发,只需要“run”就能创建一个独立的、生产级别的Spring应用。Spring Boot为Spring平台及第三方库提供开箱即用的设置(提供默认设置,存放默认配置的包就是启动器),这样我们就可以简单的开始。多数Spring Boot应用只需要很少的Spring配置。
我们可以使用SpringBoot创建java应用,并使用java –jar 启动它,就能得到一个生产级别的web工程。
10.3.SpringBoot的特点
Spring Boot 主要目标是:
- 为所有 Spring 的开发者提供一个非常快速的、广泛接受的入门体验
- 开箱即用(启动器starter-其实就是SpringBoot提供的一个jar包),但通过自己设置参数(.properties),即可快速摆脱这种方式。
- 提供了一些大型项目中常见的非功能性特性,如内嵌服务器、安全、指标,健康检测、外部化配置等
- 绝对没有代码生成,也无需 XML 配置。
更多细节,大家可以到官网查看。
11 聚合项目整合SpringBoot
SpringCloud和SpringBoot版本选择以及GA/PRE/SNAPSHOT说明,查看文档https://www.yuque.com/chaining/architects/bgr6g9
11.1添加依赖
修改父工程pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--
1.聚合工程里可以分为顶级项目(顶级工程、父工程)与子工程,这两者的关系其实就是父子继承的关系
子工程在maven里成为模块(module),模块之间是平级,是可以相互依赖的
2.子模块可以使用顶级工程里所有的子u按(依赖),子模块之间如果要使用资源,必须构建依赖(构建关系)
3.一个顶级工程可以由多个不同的子工程共同组合而成
-->
<groupId>com.chaining</groupId>
<artifactId>foodie-dev</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>foodie-dev-common</module>
<module>foodie-dev-pojo</module>
<module>foodie-dev-mapper</module>
<module>foodie-dev-service</module>
<module>foodie-dev-api</module>
<module>foodie-dev-test</module>
</modules>
<!--packaging值有pom,jar和war-->
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
parent标签作用:
用于引用父工程
1、统一管理jar包的版本,其依赖需要在子工程中定义才有效(比如此例)
2、统一的依赖管理(父工程的
3、控制插件的版本
4、聚合工程
这是Spring Boot的父级依赖,这样当前的项目就是Spring Boot项目了。spring-boot-starter-parent 是一个特殊的starter,它用来提供相关的Maven默认依赖。 使用它之后,常用的包依赖可以省去version标签。
查看spring-boot-starter-parent到底管理了哪些依赖。
进入spring-boot-starter-parent.pom中去,然后Ctrl+左击框出来的位置进入spring-boot-dependencies.pom
11.2编写配置文件
11.3编写启动类
Spring Boot项目通过main函数即可启动,我们需要创建一个启动类:
在foodie-dev-api工程中新建一个Application.class启动类,然后编写main函数:
package com.architects;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @ClassName Application
* @Description:
* @Author ning.chai@foxmail.com
* @Date 2020/12/31 0031
* @Version V1.0
**/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
11.4 编写Web控制层controller
接下来,我们就可以像以前那样开发SpringMVC的项目了!
我们编写一个controller:
代码:
package com.architects.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName HelloController
* @Description:
* @Author ning.chai@foxmail.com
* @Date 2020/12/31 0031
* @Version V1.0
**/
//@Controller
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "Hello World";
}
}
11.5 启动测试
接下来,我们运行main函数,并查看控制台:
项目启动失败,从控制台可以看到一行报错信息:Web server failed to start. Port 8080 was already in use.
解决方案:修改监听端口
重新启动
打开页面访问:http://localhost:8181/hello
测试成功了!
12 SpringBoot自动配置原理
使用SpringBoot之后,一个整合了SpringMVC的WEB工程开发,变的无比简单,那些繁杂的配置都消失不见了,这是如何做到的?
一切魔力的开始,都是从我们的main函数来的,所以我们再次来看下启动类:
我们发现特别的地方有两个:
- 注解:@SpringBootApplication
- run方法:SpringApplication.run()
12.1.了解@SpringBootApplication
点击进入,查看源码:
看一个源码之前,首先要了解他的作用,那么,类的注释,一定要看!
这里重点的注解有3个:
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
12.1.1.@SpringBootConfiguration
我们继续点击查看源码:
通过这段我们可以看出,在这个注解上面,又有一个@Configuration
注解。通过上面的注释阅读我们知道:这个注解的作用就是声明当前类是一个配置类,然后Spring会自动扫描到添加了@Configuration
的类,并且读取其中的配置信息。而@EnableAutoConfiguration
是来声明当前类是SpringBoot应用的配置类,项目中只能有一个。所以一般我们无需自己添加。
12.1.2.@EnableAutoConfiguration
关于这个注解,官网上有一段说明:
The second class-level annotation is
@EnableAutoConfiguration
. This annotationtells Spring Boot to “guess” how you want to configure Spring, based on the jardependencies that you have added. Sincespring-boot-starter-web
added Tomcatand Spring MVC, the auto-configuration assumes that you are developing a webapplication and sets up Spring accordingly.
简单翻译以下:
第二级的注解
@EnableAutoConfiguration
,告诉SpringBoot基于你所添加的依赖,去“猜测”你想要如何配置Spring。比如我们引入了spring-boot-starter-web
,而这个启动器中帮我们添加了tomcat
、SpringMVC
的依赖。此时自动配置就知道你是要开发一个web应用,所以就帮你完成了web及SpringMVC的默认配置了!
总结,SpringBoot内部对大量的第三方库或Spring内部库进行了默认配置,这些配置是否生效,取决于我们是否引入了对应库所需的依赖,如果有那么默认配置就会生效。
所以,我们使用SpringBoot构建一个项目,只需要引入所需框架的依赖,配置就可以交给SpringBoot处理了。除非你不希望使用SpringBoot的默认配置,它也提供了自定义配置的入口。
12.1.3.@ComponentScan
我们跟进源码:
并没有看到什么特殊的地方。我们查看注释:
大概的意思:
配置组件扫描的指令。提供了类似与
<context:component-scan>
标签的作用 通过basePackageClasses或者basePackages属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包
而我们的 @SpringBootApplication
注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。因此,一般启动类会放在一个比较前的包目录中。
**
12.2.默认配置原理
12.2.1默认配置类
通过刚才的学习,我们知道 @EnableAutoConfiguration
会开启SpringBoot的自动配置,并且根据你引入的依赖来生效对应的默认配置。那么问题来了:
- 这些默认配置是在哪里定义的呢?
- 为何依赖引入就会触发配置呢?
还是查看源码,查看 @EnableAutoConfiguration
源码
里面引入了一个类 AutoConfigurationImportSelector.class
引起了我们的注意,点击进去
从这个类的字面意思上来看,他就是一个用于自动配置导入的选择器,既然是选择器,那就包含了很多内容。
在类 selectImports
中我们看getAutoConfigurationEntry方法。
这和方法中我们只关注框起来的表达式,比较简单,不做翻译,直接点进去看~
重点来了!此处有一个断言,发生错误报了异常,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct."
META-INF/spring.factories,怎么找到这个配置?
在AutoConfigurationImportSelector类中,打开右侧Project,然后点击下图右上角框出来的图标(scroll form source)就会定位到AutoConfigurationImportSelector类
然后查看META-INF中的spring.factores
搜索WebMvc,找到WebMvcAutoConfiguration(当然也可以看其他的装配类,比如EmbeddedWebServerFactoryCustomizerAutoConfiguration中有tomcat相关的东西)
进入查看此类
我们看到这个类上的4个注解:
@Configuration
:声明这个类是一个配置类@ConditionalOnWebApplication(type = Type.SERVLET)
ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是是Type.SERVLET类型,也就是一个普通web工程,显然我们就是@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了tomcat依赖自然会有,后两个需要引入SpringMVC才会有。这里就是判断你是否引入了相关依赖,引入依赖后该条件成立,当前类的配置才会生效!@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
这个条件与上面不同,OnMissingBean,是说环境中没有指定的Bean这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个WebMVCConfigurationSupport的类,那么这个默认配置就会失效!
接着,我们查看该类中定义了什么:
视图解析器:
处理器适配器(HandlerAdapter):
还有很多,这里就不一一截图了…
12.2.2.默认配置属性
另外,这些默认配置的属性来自哪里呢?
我们看到,这里通过@EnableAutoConfiguration注解引入了两个属性:WebMvcProperties和ResourceProperties。这不正是SpringBoot的属性注入玩法嘛。
我们在WebMvcAutoConfiguration类中查看这两个属性类:
我们看到,这里通过 @EnableAutoConfiguration
注解引入了两个属性:WebMvcProperties和ResourceProperties。这不正是SpringBoot的属性注入玩法嘛。
我们查看这两个属性类:
WebMvcProperties.class中
找到了内部资源视图解析器的prefix和suffix属性。
ResourceProperties中主要定义了静态资源(.js,.html,.css等)的路径:
如果我们要覆盖这些默认属性,只需要在application.properties中定义与其前缀prefix和字段名一致的属性即可。
12.3.总结
SpringBoot为我们提供了默认配置,而默认配置生效的条件一般有两个:
- 你引入了相关依赖
- 你自己没有配置
1)启动器
所以,我们如果不想配置,只需要引入依赖即可,而依赖版本我们也不用操心,因为只要引入了SpringBoot提供的stater(启动器),就会自动管理依赖及版本了。
因此,玩SpringBoot的第一件事情,就是找启动器,SpringBoot提供了大量的默认启动器
2)全局配置
另外,SpringBoot的默认配置,都会读取默认属性,而这些属性可以通过自定义application.properties
文件来进行覆盖。这样虽然使用的还是默认配置,但是配置中的值改成了我们自定义的。
因此,玩SpringBoot的第二件事情,就是通过application.properties
来覆盖默认属性值,形成自定义配置。我们需要知道SpringBoot的默认属性key,非常多,有兴趣可以搜索 SpringBoot全局属性进一步学习。
13 HikariCP数据源简介
HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池。
官网:https://github.com/brettwooldridge/HikariCP
为何要使用HiKariCP?这要先从BoneCP说起:
什么?不是有C3P0/DBCP这些成熟的数据库连接池吗?一直用的好好的,为什么又搞出一个BoneCP来?因为,传说中BoneCP在快速这个特点上做到了极致,官方数据是C3P0等的25倍左右。不相信?其实我也不怎么信。可是,有图有真相啊(图片来自BoneCP官网:http://jolbox.com/benchmarks.html):
详细文档参照:HikariCP连接池
14 HikariCP和SpringBoot整合
父级工程中添加依赖
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
配置yml
############################################################
#
# web访问接口,约定8088
#
############################################################
server:
port: 8088
############################################################
#
# 配置数据源信息
#
############################################################
spring:
datasource: # 数据源的相关配置
type: com.zaxxer.hikari.HikariDataSource # 数据源类型:HikariCP
driver-class-name: com.mysql.jdbc.Driver # mysql驱动
url: jdbc:mysql://localhost:3306/foodie-shop-dev?useUnicode=true&characterEncoding=UTF-8&autoReconnect
username: root
password: root
hikari:
connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQ
minimum-idle: 5 # 最小连接数
maximum-pool-size: 20 # 最大连接数
auto-commit: true # 自动提交
idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
pool-name: DateSourceHikariCP # 连接池名字
max-lifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟
connection-test-query: SELECT 1
############################################################
#
# mybatis 配置
#
############################################################
mybatis:
type-aliases-package: com.chaining.pojo # 所有POJO类所在包路径
mapper-locations: classpath:mapper/*.xml # mapper映射文件
创建package
在foodie-dev-pojo工程中创建com.chaining.pojo
在foodie-dev-mapper工程中创建com.chaining.mapper
在foodie-dev-mapper工程中的resource创建mapper目录
启动测试
15 HikariCP数据源连接详解
############################################################
#
# 配置数据源信息
#
############################################################
spring:
datasource: # 数据源的相关配置
type: com.zaxxer.hikari.HikariDataSource # 数据源类型:HikariCP
driver-class-name: com.mysql.jdbc.Driver # mysql驱动
url: jdbc:mysql://localhost:3306/foodie-shop?useUnicode=true&characterEncoding=UTF-8&autoReconnect
username: root
password: 123456
hikari:
connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQ
minimum-idle: 5 # 最小连接数
maximum-pool-size: 20 # 最大连接数,默认是10
auto-commit: true # 自动提交
idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
pool-name: DateSourceHikariCP # 连接池名字
max-lifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟
connection-test-query: SELECT 1
- minimum-idle: 5 # 最小连接数
在测试环境中设置为5就可以了,上线以后设置成10
- maximum-pool-size: 20 # 最大连接数,默认是10
这个参数跟我们服务器配置有关,并不是数值越大越好,作者建议跟minimum-idle参数设置一致
16 Mybatis逆向生成工具
通过Mybaits-generator可以生成pojo,mapper.xml以及mapper.java,经过改造,甚至可以生成一些通用的接口和增删查改方法,极大提高了我们开发的效率.
16.1打开mybatis-generator工程
16.2修改generatorConfig.xml配置文件
<?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="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 通用mapper所在目录 -->
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.architects.my.mapper.MyMapper"/>
</plugin>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3360/foodie-shop?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=UTC"
userId="root"
password="123456">
</jdbcConnection>
<!-- 对应生成的pojo所在包 -->
<javaModelGenerator targetPackage="com.architects.pojo" targetProject="src/main/java"/>
<!-- 对应生成的mapper所在目录 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>
<!-- 配置mapper对应的java映射 -->
<javaClientGenerator targetPackage="com.architects.mapper" targetProject="src/main/java" type="XMLMAPPER"/>
<!-- 数据库表 -->
<table tableName="carousel"></table>
<table tableName="category"></table>
<table tableName="users"></table>
<table tableName="user_address"></table>
<table tableName="items"></table>
<table tableName="items_img"></table>
<table tableName="items_spec"></table>
<table tableName="items_param"></table>
<table tableName="items_comments"></table>
<table tableName="orders"></table>
<table tableName="order_items"></table>
<table tableName="order_status"></table>
</context>
</generatorConfiguration>
重点是注释的地方要与自己工程包名一致,如果运行时报数据库连接异常,看看是否与下面连接方式一致
jdbc:mysql://127.0.0.1:3360/foodie-shop?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=UTC
16.3运行GeneratorDisplay类的main函数
运行后就会生成mapper、pojo以及xml,将生成的文件拷贝到foodie-shop中去
16.4 拷贝生成文件到foodie-shop中
16.5 添加依赖
拷贝文件后,pojo会报错,因为此时我们没有依赖mybatis-plus,需要在foodie-shop父级工程中依赖tk.mybatis
<!-- 通用mapper逆向工具 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
在foodie-shop-api中添加配置
############################################################
#
# mybatis mapper 配置
#
############################################################
# 通用 Mapper 配置
mapper:
mappers: com.architects.my.mapper.MyMapper
not-empty: false #在数据操作的时候判断为空时,是否加!=""
identity: MYSQL
拷贝MyMapper接口
把逆向工程中的MyMapper接口,拷贝到foodie-shop-mapper中
16.6启动测试
启动正常,说明我们工程没有问题。
17关于Restful Web webservice
详细介绍看:http://www.ruanyifeng.com/blog/2011/09/restful.html
总结如下:
- 通信方式
- 传递消息
- 无状态
服务器在接收客户端请求的时候,没必要之前动作前后的信息,也就是无状态
- 独立性
使用Restful之后,系统和系统之间就解耦了,之间的通信也是
17.1设计规范
- GET
在Restful通常用于获取资源,请求示例如下
/order/{id}
- POST
通常用于保存资源,请求示例如下
/order
- PUT
用于更新资源,请求示例如下
/order/{id}
- DELETE
用于删除操作,请求示例如下
/order/{id}
注意的是,在restful请求中,不能出现动词,只能出现一些名词