Spring boot 学习笔记
参考资料
https://spring.io/projects/spring-boot/#learn
官方文档和API
2.2.0 CURRENT GA | Reference Doc. | API Doc. |
---|---|---|
2.2.1 SNAPSHOT | Reference Doc. | API Doc. |
2.1.10 SNAPSHOT | Reference Doc. | API Doc. |
2.1.9 GA | Reference Doc. | API Doc. |
1.5.22 GA | Reference Doc. | API Doc. |
项目初始化
在线初始化:https://start.spring.io/
Eclipse 安装Spring Tools插件 或者下载Spring官方的STS整合版。
IntelliJ IDEA 安装Spring Assistant插件。
Spring Boot CLI初始化项目:
You can download the Spring CLI distribution from the Spring software repository:
开发系统要求
使用Spring Boot 2.1.9.RELEASE
JDK版本:
Java 8 and is compatible up to Java 12 (included).
Spring版本:
Spring Framework 5.1.10.RELEASE or above is also required.
构建工具版本:
Build Tool | Version |
---|---|
Maven | 3.3+ |
Gradle | 4.4+ |
Servlet 容器
Spring Boot supports the following embedded servlet containers:
Name | Servlet Version |
---|---|
Tomcat 9.0 | 4.0 |
Jetty 9.4 | 3.1 |
Undertow 2.0 | 4.0 |
You can also deploy Spring Boot applications to any Servlet 3.1+ compatible container.
第一个HelloWorld
参考官方文档10. Installing Spring Boot:
步骤:
-
新建一个基于Maven 的 Spring boot Java 工程
-
自动生成启动类
-
配置文件中修改默认端口
-
编写Controller类
-
运行程序
下面是一个典型的程序结构:
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
|
+- repository
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
Application.java 将声明 main 方法和 @SpringBootApplication
1.使用插件或者在线网页进行spring boot项目的初始化
-
jdk版本 8
-
maven项目
-
java语言
-
设置项目的路径等配置
2.选择spring boot版本 和 工具支持
-
创建spring web项目 就要勾选 Web>Spring Web
-
以后需要spring data jpa项目 就要勾选 SQL>Spring Data JPA -对应需要配置数据源
-
如此类推
3.自动生成程序入口启动类:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootDemo01Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemo01Application.class, args);
}
}
通常建议将应用的main类放到其他类所在包的顶层(root package),项目启动时自动扫描main启动类所在的根路径com.example.demo下所有带spring组件注解的类:
@Component -无法界定属于下面哪个具体的层的时候使用,例如:AOP、LOG、工具类…
@Repository - 持久层
@Service -业务层
@Controller -控制层
@RestController -控制层-Restful风格API设计
4.默认配置文件
src\main\resources\application.properties
可以修改下端口号防止端口占用:
server.port=8081
5.自定义一个web层类
package com.example.demo.hello.web;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController
{
@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
}
6.启动项目
选中 SpringBootDemo01Application.java文件 Run as…>Spring Boot App
启动成功后打开浏览器访问:http://localhost:8081/hello
7.Maven介绍
Maven用户可以继承 spring-boot-starter-parent 项目来获取合适的默认设
置。该parent项目提供以下特性:
-
默认编译级别为Java 1.6
-
源码编码为UTF-8
-
一个Dependency management节点,允许你省略常见依赖的 标
签,继承自 spring-boot-dependencies POM。 -
恰到好处的资源过滤
-
恰到好处的插件配置(exec插件,surefire,Git commit ID,shade)
-
恰到好处的对 application.properties 和 application.yml 进行筛选,
包括特定profile(profile-specific)的文件,比如 applicationfoo.
properties 和 application-foo.yml最后一点:由于配置文件默认接收Spring风格的占位符( ${…} ),所以Maven
filtering需改用 @…@ 占位符(你可以使用Maven属性 resource.delimiter 来覆
盖它)。
继承starter parent
如果你想配置项目,让其继承自 spring-boot-starter-parent ,只需
将 parent 按如下设置:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
注:你应该只需在该依赖上指定Spring Boot版本,如果导入其他的starters,放心
的省略版本号好了。更多starters :参考官方文档 Table 13.1. Spring Boot application starters
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
改变Java版本
<properties>
<java.version>1.8</java.version>
</properties>
使用Spring Boot Maven插件
Spring Boot包含一个Maven插件,它可以将项目打包成一个可执行jar。如果想使用
它,你可以将该插件添加到 节点处:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注:如果使用Spring Boot starter parent pom,你只需添加该插件而无需配置它,除非你想改变定义在partent中的设置。
Spring Boot Web开发
SpringBoot热部署spring-boot-devtools
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
在web开发中,静态资源的访问是必不可少的,如:图片、js、css 等资源的访问。spring Boot 对静态资源访问提供了很好的支持,基本使用默认配置就能满足开发需求。
默认静态资源映射
一、Spring Boot 对静态资源映射提供了默认配置
Spring Boot 默认将 /** 所有访问映射到以下目录:
v classpath:/static
v classpath:/public
v classpath:/resources
v classpath:/META-INF/resources
如果上述目录有多张同名不同内容的的图片fengjing.jpg,当我们访问地址 http://localhost:8080/fengjing.jpg 的时候,显示哪张图片?
优先级顺序为:
META-INFO/resources > resources > static > public
如:在resources目录下新建 META-INFO/resources 、public、resources、static 四个目录,并分别放入 a.jpg b.jpg c.jpg d.jpg 四张不同的图片:
浏览器分别访问:
http://localhost:8081/a.jpg
http://localhost:8081/b.jpg
http://localhost:8081/c.jpg
http://localhost:8081/d.jpg
均能正常访问相应的图片资源。那么说明,Spring Boot 默认会挨个从META-INFO/resources 、 resources 、static、public 里面找是否存在相应的资源,如果有则直接返回。
二、自定义静态资源映射
在实际开发中,可能需要自定义静态资源访问路径,那么可以继承WebMvcConfigurerAdapter来实现。
第一种方式:静态资源配置类
package com.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//将所有/static/** 访问都映射到classpath:/static/ 目录下
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
访问:http://localhost:8081/static/c.jpg 能正常访问static目录下的c.jpg图片资源。
第二种方式:在application.properties配置
在application.properties中添加配置:
spring.mvc.static-path-pattern=/static/**
重启项目,访问:http://localhost:8081/static/c.jpg 同样能正常访问static目录下的c.jpg图片资源。
Spring Boot 中文乱码解决
中文乱码可能发生的环境:
1.数据库编码
2.IDE工具编码
3.项目文件编码
4.项目Web开发设置
4.部署容器端口编码
5.服务器字体支持
一、spring boot项目修改application.properties配置文件
增加如下配置:
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
server.tomcat.uri-encoding=UTF-8
二、响应时发生乱码?
此时拦截器中返回的中文已经不乱码了,但是controller中返回的数据依旧乱码。
修改controller的@RequestMapping修改如下:
@RequestMapping(value = "/listForDoing", method=RequestMethod.POST, produces="application/json;charset=UTF-8")
这种方法的弊端是限定了数据类型,更好的办法是配置全局编码控制:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
return converter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
converters.add(responseBodyConverter());
}
}
便可以解决SpringBoot的中文乱码问题了。
三、Spring Boot使用FastJson中文乱码解决:
http://412887952-qq-com.iteye.com/blog/2413390
Spring Boot 集成 spring-data-jpa
步骤:
1.在pom.xml文件中添加Spring Boot Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2.配置数据源
#mysql datasource
spring.datasource.url=jdbc:mysql://localhost:3306/demo?serverTimezone=GMT&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#spring data jpa & mysql
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
hibernate.implicit_naming_strategy解释是:
当一个实体没有显式地命名它映射到的数据库表时,我们需要隐式地确定该表的名称。或者当特定属性没有显式地命名它映射到的数据库列时,我们需要隐式地确定该列的名称。说的简单点就是表或者属性没有指定使用名称,我的理解就是没有用@TableName和@Column。(When an entity does not explicitly name the database table that it maps to, we need to implicitly determine that table name. Or when a particular attribute does not explicitly name the database column that it maps to, we need to implicitly determine that column name.)它有以下5个属性,由于篇幅有限(我太懒-.-)。并且没有得出具体结论:
-
1.org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
-
2.org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
-
3.org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
-
4.org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
-
5.org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
但是我们依然可以自己修改命名策略。然后在配置文件中设置自己的命名策略
hibernate.physical_naming_strategy的解释是:
used to convert a “logical name” (either implicit or explicit) name of a table or column into a physical name (e.g. following corporate naming guidelines),翻译后:物理命名策略,用于转换“逻辑名称”(隐式或显式)的表或列成一个物理名称。这个 physical_naming_strategy 命名策略有两个子属性,如下:
- 1.PhysicalNamingStrategyStandardImpl:不做修改,直接映射
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl - 2.SpringPhysicalNamingStrategy:在进行领域映射时,首字母小写,大写字母变为下划线加小写
ex: LoginName --> login_name
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
3.编写domain、repository、service、web(Controller)层
domain
package com.example.demo.hello.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t_hello")
public class Hello
{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String msg;
private String myTestMsg;
public Long getId() {
return id;
}
public String getMsg() {
return msg;
}
public void setId(Long id) {
this.id = id;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getMyTestMsg() {
return myTestMsg;
}
public void setMyTestMsg(String myTestMsg) {
this.myTestMsg = myTestMsg;
}
}
repository层
package com.example.demo.hello.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.example.demo.hello.domain.Hello;
/**
* PagingAndSortingRepository
* 基础CRUD功能
* 分页+排序功能
* 自定义查询功能
* 统计分析功能
*/
@Repository
public interface HelloRepository
extends PagingAndSortingRepository<Hello, Long>{
}
service层
package com.example.demo.hello.service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.example.demo.hello.domain.Hello;
public interface IHelloService
{
public void saveOrUpdate(Hello hello);
public void delete(Hello hello);
public Hello findOne(Long id);
public Page<Hello> findPage(Pageable pageable);
}
package com.example.demo.hello.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import com.example.demo.hello.domain.Hello;
import com.example.demo.hello.repository.HelloRepository;
@Service
public class HelloService implements IHelloService
{
@Autowired
private HelloRepository helloRepository;
@Override
public void saveOrUpdate(Hello hello) {
helloRepository.save(hello);
}
@Override
public void delete(Hello hello) {
helloRepository.delete(hello);
}
@Override
public Hello findOne(Long id) {
return helloRepository.findById(id).get();
}
@Override
public Page<Hello> findPage(Pageable pageable) {
return helloRepository.findAll(pageable);
}
}
web(Controller) 层
package com.example.demo.hello.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.hello.domain.Hello;
import com.example.demo.hello.service.IHelloService;
@RestController("/hello")
public class HelloController
{
@Autowired
private IHelloService helloService;
@PostMapping
public void save(Hello hello) {// id = null
helloService.saveOrUpdate(hello);
}
@PutMapping
public void update(Hello hello) {// id = 1
helloService.saveOrUpdate(hello);
}
@DeleteMapping
public void delete(Long id) {
Hello hello = helloService.findOne(id);
if(null!=hello)
helloService.delete(hello);
}
@GetMapping
public Hello findOne(Long id) {
return helloService.findOne(id);
}
}
4.运行程序,并使用postman调试后台:
POST:http://localhost:8081/hello?msg=你好springboot!
PUT:http://localhost:8081/hello?id=1&msg=我们更新msg字段
GET:http://localhost:8081/hello?id=1
DELETE:http://localhost:8081/hello?id=1
RAP2 快速入门
RAP是一个可视化接口管理工具 通过分析接口结构,动态生成模拟数据,校验真实接口正确性, 围绕接口定义,通过一系列自动化工具提升我们的协作效率。
可视化编辑,完善的版本控制,各种格式的导入导出。让前后端约定接口的工作变得十分简单。
RAP会自动根据接口文档生成Mock接口(前端使用),这些接口会自动生成模拟数据,支持复杂的生成逻辑。
使用RESTful的风格来开发接口
1.先从传统设计接口的方式来看:
新增一个员工:http://www.demo.cn/finance/employee/createEmp
删除一个员工:http://www.demo.cn/finance/employee/deleteEmp
修改一个员工:http://www.demo.cn/finance/employee/updateEmp
获取员工列表:http://www.demo.cn/finance/employee/listEmp
一个非常简单的需求产生的问题:
1.每一个操作,都需要一个独立的url去操作,因为我们对员工的动作都需要反映在url里面.
2.会产生大量的url,非常不方便接口的维护和文档的维护
3.如果有不同的响应方式,我们可能需要额外的参数,甚至不同的url来描述
4.请求参数包含在请求地址中,无法针对性做缓存
2.使用RESTful风格的接口
接口 :http://www.demo.cn/finance/employee
新增一个员工:POST
删除一个员工:DELETE /id
修改一个员工:PUT /id
获取员工列表:GET
获取一个员工列表:GET /id
通过HTTP的请求方式来给予这些请求的不同含义,动作设计.
使用YAML代替Properties
Spring Boot单元测试(Mock)
https://www.cnblogs.com/a8457013/p/7825087.html
https://blog.youkuaiyun.com/liuchuanhong1/article/details/53495004
SpringBoot的日志管理
实现日志管理的三种方式:
- 1.使用Logback自定义配置实现高级日志
- 2.使用SLF4J API输出日志
- 3.使用@Slf4j注解
扩展阅读:
日志级别的选择:Debug、Info、Warn、Error还是Fatal
https://blog.youkuaiyun.com/qq_27088383/article/details/52163388
springBoot完美配置log4j2
https://blog.youkuaiyun.com/V_Come_On/article/details/79408773
Spring AOP实现后台管理系统日志管理
https://blog.youkuaiyun.com/myron_007/article/details/54927529
Spring Boot 日志配置(超详细)
https://blog.youkuaiyun.com/Inke88/article/details/75007649
spring-boot-fileupload文件上传
spring-boot-https协议
spring-boot-redis分布式集群
spring-boot-ehcache缓存
spring-boot-websocket网络通信协议
spring-boot-mybatis
SpringBoot与MicroService微服务
http://spring.io/blog/2015/07/14/microservices-with-spring