spring boot
一、基本介绍
它是什么?
Spring: spring是03年兴起的一个轻量级Java框架,为了解决企业级应用开发笨重臃肿的问题,目的是简化开发。
Spring Boot: 它是简化Spring框架开发的框架。
它为什么诞生,能做什么?
随着Spring的普及,为了解决大量繁琐的XML配置和第三方整合配置,14年正式发布Spring boot,它默认配置了很多框架的使用方式,整合了所有的框架,核心思想是约定优于配置。可以让开发者通过少量的代码就能创建一个独立的、产品级别的Spring应用。
特性
- 搭建项目快,没有冗余代码生成和XML配置的要求,开箱即用,提供各种默认配置来简化项目配置;
- 内嵌容器,省去了配尊Tomcat的繁琐;
- Starter自动依赖和版本控制
- 方便监控,使用SpringBootActuator组件提供了应用的系统监控,可以查看应用配置的详细信息;
微服务
微服务:要求开发一个应用时,必须构建成一系列的小服务的组合,并且每一个服务运行在自己的进程中,可以用http的方式进行互通。
优点:省了调用资源。每个功能元素的服务都是一个可替换的、可独立升级的软件代码
单体架构
单体架构:指将所有服务都封装在一个应用中,各个功能都放在一个war包内。
优点:易于开发和测试;十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了
缺点:项目过于臃肿;资源无法隔离;无法灵活拓展。
如何构建微服务
- 构建一个个功能独立的微服务应用单元,可以使用springboot,可以帮我们快速构建一个应用;
- 大型分布式网络服务的调用,这部分由spring cloud来完成,实现分布式;
- 在分布式中间,进行流式数据计算、批处理,采用spring cloud data flow
二、快速入门
开发准备
软件:JDK、Maven、IDEA、Springboot。
配置
Maven配置
修改Jar包放置路径,默认是C盘,maven3/conf/settings.xml。
可以在localRepository更改默认路径。
<localRepository>D:/repository/.m2/repository</localRepository>
maven项目JDK的设置
<profile>
<id>jdk-1.8</id>
<activation>
<jdk>1.8</jdk>
<activeByDefault>true</activeByDefault>
</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>
maven镜像的设置
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
IDEA配置
在启动界面Configure -> Setting -> build -> build tools -> Maven。
- 把Maven文件夹路径修改为自己的路径,如果用的是idea的maven就可以不修改。
- Maven 的Setting文件的路径修改为自己的路径,如果用的是idea的maven就可以不修改。
- Maven jar的存放路径修改为之前localRepository标签中写的路径。
注:不能在打开项目以后的界面中修改,打开项目以后的界面修改的是当前项目的配置,启动界面修改的是以后所有新建项目的配置。)
使用Spring boot进行web开发
-
Spring boot项目下载:
- 在官网下载 Spring项目下载
- IDEA集成
-
可直接启动项目,访问localhost 8080端口。
-
点击Maven工具,点击package,进行自动打包,打包完成之后,会在target文件夹中出现刚刚打包jar包。
-
把上述jar放到其他文件夹,用java命令: java -jar jar包名称 来启动springboot项目。
Springboot的结构说明
pom.xml文件:
- 项目元数据信息:创建时候输入的Project Metadata部分,也就是Maven项目的基本元素,包括:groupld、artifactld、version、name、description等
- parent:继承spring-boot-start-parent的依赖管理,控制版本与打包依赖等功能
dependencies:项目具体依赖。 - build:构建配置部分。默认使用了spring-boot-maven-plugin,配合Spring-boot-starter-parent就可以把Spring boot应用打包成JAR直接运行。
<?xml ...?>
<project ...>
模块版本号
<modelVersion>...</modelVersion>
父级版本的引入,集成了所有父级的配置
<parent>...</parent>
新建项目的时候进行描述的项目信息
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<name>...</name>
<description>...</description>
构建项目所需要的的公共变量
<properties> 编码格式 jdk的版本号
<java.version>...</java.version>
</properties>
项目所需要得依赖配置
<dependencies>
web模块的支持
<dependency>
...
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
test测试模块的支持
<dependency>
...
<artifactId>spring-boot-starter-test</artifactId>
...
</dependency>
</dependencies>
构建配置
<build>
进行这个工程打jar包的插件
<plugins>
<plugin>
...
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
starter版本号管理
在 <parent>
中Ctrl+点击进入<artifactId>spring-boot-starter-parent</artifactId>
新出现的页面中在 <parent>
中Ctrl+点击进入<artifactId>spring-boot-dependencies</artifactId>
,在这里管理版本号
三、原理分析
SpringBoot启动类解析 @SpringBootApplication
- @SpringBootConfiguration :springboot的配置类 -->Configuration --> 表明这是一个配置类 ->@Component 加载到spring容器
- @EnableAutoConfiguration :开启自动配置功能
- @AutoConfigurationPackage:自动配置包 :
- @Import({Registrar.class}) :把启动类所在的包进行默认扫描,该包下的所有类都会被扫到spring容器中进行管理,如果放在默认配置包(启动类包)之外,Spring boot将无法加载,比如将Controller文件放到启动类包之外,访问8080,将无法找到路径。
- @Import({AutoConfigurationImportSelector.class}) :加载指定的类到spring容器中去,其中AutoConfigurationImportSelector 是自动配置导入选择器,根据项目来判断你的项目需要哪些配置信息,然后把默认的配置内容导入到spring容器中进行管理
- @AutoConfigurationPackage:自动配置包 :
- @ComponentScan : 组件扫描和自动装配,用来指定扫描容器的范围
图示
四、配置说明
配置原因
- 方便我们修改spring boot默认的配置。
- 我们有其他的信息需要保存在配置文件中。
配置文件种类
- properties文件:是默认配置文件
- yml或者yaml文件
注:
- properties和yml一起出现时,properties生效
- Spring boot 默认读取以 application 开头的配置文件;
- 文件放入在src/main/resources 目录或者是类路径/config目录下
properties
示例
person1.name=wangwu
person1.sex=ff
person1.age=22
person1.isMerried=true
person1.pets[0]=小狗
person1.pets[1]=小猫
person1.pets[2]=小驴
person1.friends[0].name=qqqq
person1.friends[0].sex=nan
person1.friends[1].name=wwww
person1.friends[1].sex=nv
yml
yml的全程为YAML 它是一种标记语言,它是一种直观的被电脑识别的数据序列化格式,并且容易被人类阅读,这种标记语言和其他标记语言不同的地方是,它是以数据为中心,比json、xml等更合适做配置文件
基本语法
- key:value的格式(value前面的空格不能少,可以有多个,不能用tab代替);
- 大小写敏感;
- 字符串默认不需要使用引号,单引号和双引号的区别在于是否能用转义字符,双引号可以
- 注释方式: #
支持的数据类型
- 字面量:直接量,单个不能被拆分的值(数字、字符串、布尔)
- 对象:键值对形式存在
- 数组:字面量、对象的集合
示例
server:
port: 8081
字面量
person:
name: za
sex: s
age: 22
isMerried: false
对象
friend:
name: lisi
sex: nv
对象的json格式,在这也可被接受
otherfriend: {name: lisi,sex: nv}
数组
pets:
- 小狗
- 小猫
- 效率
pets1: [小猫, 小狗, 小猪]
friends: [{name: lisi,sex: nv}, {name: lisisi,sex: nv}]
使用配置
@Component
@ConfigurationProperties(prefix = "person") prefix: 配置文件中的前缀
public class Person { 省略了 toString get set
private String name;
private Integer age;
private String sex;
private boolean isMerried;
private Friend friend;
private String[] pets;
private List<Friend> friends;
}
测试
@SpringBootTest
class SpringbootStudyHelloApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
也可以用properties来测试。
注: 若出现中文乱码,在setting -> editor -> file Coding 改成UTF-8 ,若还是没有效果,把中文重新写一遍,因为输入的时候编码已经不同了。
value注入
- 三种书写方式:
${字面量}、${配置文件中取值}
以及使用#{SpEL表达式}
等同于:
<bean id=””Persom>
<property name=”lastName” value=”字面量/${key}从环境变量、配置文件中获取值/#{SpEL}”></property>
<bean/>
注入测试
@Component
public class Person { 省略了 toString get set
@Value("${person.name}")
private String name;
@Value("#{11*4}")
private Integer age;
@Value("#{person.sex}")
private String sex;
@Value("${person.isMerried}")
private boolean isMerried;
private Friend friend;
private String[] pets;
private List<Friend> friends;
}
自定义名称properties的读取
注解给出文件路径即可@PropertySource("classpath:????.properties")
测试
新建Person2.properties文件。
@Component
@ConfigurationProperties(prefix = "person2")
public class Person { 省略了 toString get set
private String name;
private Integer age;
private String sex;
private boolean isMerried;
private Friend friend;
private String[] pets;
private List<Friend> friends;
}
五、web开发示例
MVC配置
@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {
@Override 访问根路径自动跳转至登陆页面。
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login.html");
}
@Override 添加拦截器,(可以看在下面看了拦截器以后再来看这段代码)。
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerIntercept())
.addPathPatterns("/**") 拦截所有
.excludePathPatterns("/","/login.html","/user/login","/css/**","/js/**","/img/**"); 这些请求排除在外
}
}
Controller
登录配置,省略了对数据的增删改
利用session对登录的用户进行简单验证。
@Controller
public class UserController {
@RequestMapping("/user/login")
public String login(String username, String password, ModelMap modelMap, HttpSession session){
if (!StringUtils.isEmpty(username)&&!StringUtils.isEmpty(password)&&
"admin".equals(username)&&"admin".equals(password)){
session.setAttribute("username",username);往session中放用户名称。以便拦截器检查。
return "redirect:/user/list"; 重定向转跳到list.html
}else{
modelMap.addAttribute("login_error","用户名密码错误");
return "login"; 返回到login.html页面
}
}
@RequestMapping("/user/list")
public String findAll(ModelMap modelMap){
List<Users> users = usersRepository.findAll();
modelMap.addAttribute("list",users);
return "list";
}
}
拦截器
为什么要添加拦截器?
防止不经过登入页面,避免直接访问其他需要登录用户信息的页面。
- 书写一个自定义拦截器类,功能就是检测是否登录;
- 在WebMvcConfigure类里重写添加拦截器的方法,并进行业务的书写;
- 测试是否生效;
public class LoginHandlerIntercept implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object username = request.getSession().getAttribute("username");
if (username != null){
return true;
}else {
request.setAttribute("login_error", "请先登录");
request.getRequestDispatcher("/").forward(request,response);
return false;
}
}
}
UsersRepository
public interface UsersRepository {
List<Users> findAll();
int deleteUserById(int id);
}
Spring boot配置
spring.thymeleaf.cache=false 阻止前端缓存
资源
在resource下存放静态文件夹static,static下添加css、js、img文件。
在resource下存放模板文件夹template,template下添加html文件。
六、RESTful
RESTful相关介绍
URI、URL、URN
URI、URL、URN三者的关系,URI包括URL和URN。URL和URN有交叉
名称 | 举例 | 解释 |
---|---|---|
URI | http://bitpoetry.io/posts/hello.html#intro | 服务器上每一种资源,比如文档、图像、视频片段、程序都由一个通用资源标志服进行定位 |
URL | http://bitpoetry.io/posts/hello.html | URL是URI的子集,是访问网络位置的方式。 |
URN | bitpoetry.io/posts/hello.html#intro | URN是URI的子集,包括名字(给定的命名空间内),但是不包括访问方式 |
产生背景
太多不同的设备访问同一个服务器,必须有一种统一的机制,方便不同的前端设备与后端进行通信,于是REST诞生了,它可以通过一套统一的接口为WEB,IOS和Android提供服务。
REST概念
REST :( RepresentationalStateTransfer 表述性状态转移)它是一种架构风格。
原则
- 网络上的所有事物都被抽象为资源
- 每个资源都有一个唯一的资源标志符
- 同一个资源具有多种表现形式(xml,json等);
- 对资源的各种操作不会改变资源标志符
- 所有的操作都是无状态的。
对无状态的理解:
http协议无状态中的【状态】到底指的是什么?!作者:小小脑袋
RESTful 概念
遵循了rest原则的web服务,rest式的web服务是一种ROA(面向资源的架构),RESTful架构一个核心概念是“资源”(Resource)
互联网中,客户端和服务端之间的互动传递的就只是资源的表述,我们上网的过程,就是调用资源的URL,获取它的不同表现形式的过程。这种互动只能使用无状态协议HTTP。也就是说,服务端必须保存所有的状态,客户端可以使用HTTP的几个基本操作,包括GET(获取)、POST(创建)、PUT(更新)、DELETE(删除),使得服务端上的资源发生“状态转化”(StateTransfer),也就是所谓的“表述性状态转移
举例
方法 | URL | 功能 |
---|---|---|
GET | /users | 获取用户列表 |
GET | /users/1 | 获取id为1的用户 |
POST | /users | 创建一个用户 |
PUT | /users/1 | 替换id为1的用户 |
PATCH | /users/1 | 修改id为1的用户 |
DELETE | /users/1 | 删除id为1的用户 |
GET | /users/1/products | 获取id为1用户下的产品列表 |
GET | /users/1/products/2 | 获取id为1用户下id为2的产品 |
POST | /users/1/products | 在id为1用户下,创建一个产品 |
PUT | /users/1/products/2 | 在id为1用户下,替换id为2的产品 |
PATCH | /users/1/products/2 | 修改id为1的用户下id为2的产品 |
DELETE | /users/1/products/2 | 删除id为1的用户下id为2的产品 |
RESTful 应用
Spring Boot 全面支持开发RESTful程序,通过不同的注解来支持前端的请求。
- @GetMapping,处理Get请求
- @PostMapping,处理Post请求
- @PutMapping,用于更新资源
- @DeleteMapping,处理删除请求
- @PatchMapping,用于更新部分资源
Controller中的映射注解
- @PathVariable,用于接收url路径上的参数
- @ModelAttribute,用于直接接收url?后面的参数如 url?id=123&name=456,然后直接转为Pojo
Springboot下进行RESTful的开发流程
配置
pom.xml
添加Jpa、mysql依赖
添加热部署依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>开启热部署
<fork>true</fork>
</configuration>
</plugin>
- 在setting -> build -> compiler 中 在 build project automatically 复选框√。双击shift,输入reg,选择registry
- compiler.automake.allow.when.app.running 复选框√。
- 在界面右上角打开 edit configuration 选择 configuration 标题卡,在 running Application Update Policies 中 两个都选 Update classes and resources。
properties配置
数据库配置
数据库url地址
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&
useUnicode=true&characterEncoding=utf-8&useSSL=true
数据库用户名密码
spring.datasource.username=root
spring.datasource.password=123456
mysql的驱动类,也可以这样写:com.mysql.jdbc.Driver
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Jpa配置
自动生成开启,让表数据会自动跟随entity类的变化而变化
spring.jpa.properties.hibernate.hbm2ddl.auto=update
方言选择mysql
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
开启sql打印
spring.jpa.show-sql=true
开启sql格式化
spring.jpa.properties.hibernate.format_sql=true
利用idea右侧数据库工具连接上数据库
利用Jpa生成实体类
- project structure - > Modules -> 点击“+” -> 选择Jpa, -> 点击右侧“+” -> 选择第一个persistence.xml。-> 点击ok
- 在界面左侧出现persistence 标题卡 选择唯一的那个项目,右键选择Generate persistence Mapping -> 选择By DataSource Schema ,选择数据库,选择实体类生成所在的包。为想要生成table打上勾,实体类前缀 后缀为空。最后选择yes。
Jpa接口
public interface UsersRepository extends JpaRepository<UsersEntity,Integer> {
}
Controller
@RestController
public class UsersController {
@Autowired
private UsersRepository usersRepository;
查询所有数据
@GetMapping(value = "users")
public List<UsersEntity> findAll(){
return usersRepository.findAll();
}
根据id查询对象
@GetMapping(value = "users/{id}")
public UsersEntity findById(@PathVariable int id){
return usersRepository.findById(id).get();
}
保存对象
@PostMapping(value = "users")
public UsersEntity saveUsers(UsersEntity usersEntity){
return usersRepository.save(usersEntity);
}
修改对象
@PutMapping(value = "users")
public UsersEntity updataUsers(@ModelAttribute UsersEntity usersEntity){
return usersRepository.saveAndFlush(usersEntity);
}
根据id删除对象
@DeleteMapping(value = "users/{id}")
public void deleteById(@PathVariable int id){
usersRepository.deleteById(id);
}
}
Spring Data REST
简介
- Spring Data REST 作为Spring Data 项目的子集,开发者只需要使用注解@RepositoryRestResource标记,就可以把整个Repository转换为HAL风格的REST资源,目前已支持Spring Data JPA、Spring Data MongoDB、Spring Data、Neo4j等等。
- 简单点说,Spring Data REST把我们需要编写的大量REST模板接口做了自动化实现,并符合HAL的规范
- HAL(Hypertxt Application Language)是一个被广泛采用的超文本表达的规范。
- 官方文档
目前github提供的api就是这种风格。在返回结果中添加额外的信息(连接)之后,服务器端提供的表达可以帮助客户端更好的发现服务端所支持的动作。
示例
除了上面的那些依赖还需添加spring-boot-starter-data-rest依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
Jpa接口
通过Jpa规则实现增删改查。无需写sql语句
@RepositoryRestResource(path = "users")
public interface UsersRepository extends JpaRepository<Users,Integer> {
Users findByUsername(@Param("username")String username);
}
测试
可用postman等测试接口的软件或浏览器插件测试接口。
可测试功能以下常用操作。
REST里的常用操作
- Get:查询所有,根据id查询,分页查询,排序分页查询,条件查询
- Post:新增
- Put:修改
- Patch:修改
注:PUT 和PATCH 两种修改的区别
- 两者都是 修改 如果没有就新添加,如果有就修改
- PUT 需要把所有的修改信息都填上。
- PATCH 只需要把目标修改i信息填上即可。
注:手写Controller和REST 是可以共存的。